Вопрос по static, design-patterns, c++, singleton, lazy-initialization – C ++ различные реализации синглтона

2

Я обычно реализую шаблон синглтона таким образом:

class Singleton
{
    public:
        virtual ~Singleton() {}

        static Singleton& GetInstance()
        {
            static Singleton instance;
            return instance;
        }

    private:
        Singleton();
        Singleton(const Singleton&);
        Singleton& operator=(const Singleton&);
}

Недавно я столкнулся с этой реализацией, которая немного отличается:

class Singleton
{
    public:
        Singleton();
        virtual ~Singleton() {}

        static Singleton& GetInstance()
        {
            return instance;
        }

    private:
        Singleton(const Singleton&);
        Singleton& operator=(const Singleton&);

        static Singleton instance;
}

Singleton Singleton::instance;

Какая реализация лучше?

Не опасно ли не делать конструктор закрытым (2-я реализация)?

Благодарю.

Ваш Ответ

5   ответов
3

Есть разница. В первом случаеinstance инициализируется при первом вызове функции. Во втором случае он инициализируется при запуске программы.

Если вы делаетеpublic конструктор - это неsingletonпоскольку он может быть создан любым пользователем

4

сделанную в других ответах.

Позвольте мне добавить это:

public:
    Singleton();
    virtual ~Singleton() {}

Дизайнер этого конкретного класса чувствовал необходимость разрешить:

derivation from this Singleton class, say the derived class is called DerSingleton DerSingleton can have instances which can be deleted with a pointer to Singleton (so DerSingleton is not a singleton)

Любой экземплярDerSingleton такжеSingleton экземпляр по определению, поэтому следует, что еслиDerSingleton инстанцируется,Singleton это не синглтон.

Таким образом, этот дизайн утверждает две вещи:

this class is a singleton this class is not a singleton
0

что создание экземпляра во втором примере является поточно-ориентированным.

Вы абсолютно правы, однако, конструктор должен быть закрытым.

Вот связанный вопрос:https://stackoverflow.com/a/10479084/1158895

1

Вторая реализацияwrong, Конструктор по умолчанию должен быть закрытым. Как это, это не синглтон как таковой. Кроме того, различия между реализациями упомянуты в ответах @Andrew и @Brady.

3

если вы попытаетесь использовать синглтон во время инициализации другой переменной уровня пространства имен или статического члена класса. В первом случае, поскольку фактический объект создается по требованию во время первого вызова функции, поведениеduring contruction будет хорошо определено. Во втором случае все ставки отключены, поскольку относительный порядок инициализации статических объектов из разных единиц перевода не определен.

Также обратите внимание, что в то время как первый безопасен во времяconstructionЭто может быть не во время уничтожения. То есть, если объект со статической продолжительностью хранения не использует singleton во время построения, он может быть инициализирован перед экземпляром singleton. Порядок уничтожения обратен порядку построения, и в этом конкретном случае синглтон будет уничтожен раньше другого объекта. Если этот объект использует синглтон в своем деструкторе, он вызовет неопределенное поведение.

Похожие вопросы