О двух видах одноэлементных паттернов в C ++ - PullRequest
1 голос
/ 07 сентября 2011

Когда я ищу информацию о шаблоне синглтона для C ++, я всегда нахожу примеры, подобные этому:

class Singleton
{
    public:
        ~Singleton() {
        }

        static Singleton* getInstance()
        {
            if(instance == NULL) {
                instance = new Singleton();
            }
            return instance;
        }

    protected:
        Singleton() {
        }

    private:
        static Singleton* instance;
};

Singleton* Singleton::instance = NULL;

Но этот вид синглтона, похоже, тоже работает:

class Singleton
{
    public:
        ~Singleton() {
        }

        static Singleton* getInstance()
        {
            return &instance;
        }

    protected:
        Singleton() {
        }

    private:
        static Singleton instance;
};

Singleton Singleton::instance;

Полагаю, что второй синглтон создается в начале программы, в отличие от первого, но единственное ли это отличие?

Почему мы находим в основном первое?

Ответы [ 5 ]

3 голосов
/ 07 сентября 2011

http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14

фиаско статического порядка инициализации очень тонкое и обычно неправильно понятый аспект C ++. К сожалению это очень трудно обнаружить - ошибки часто возникают до того, как начинается main ().

Короче говоря, предположим, что у вас есть два статических объекта x и y, которые существуют в отдельные исходные файлы, скажем, x.cpp и y.cpp. Предположим далее, что инициализация для объекта y (обычно конструктор объекта y) вызывает некоторый метод для объекта x.

Вот и все. Это так просто.

Трагедия в том, что у вас 50% -50% вероятности смерти. Если сначала происходит инициализация модуля компиляции для x.cpp, все Что ж. Но если модуль компиляции для y.cpp инициализируется первым, тогда инициализация y будет запущена до инициализации x, и ты тост Например, конструктор y может вызвать метод на x объект, но объект x еще не был построен.

Первый метод, который вы перечислили, полностью устраняет эту проблему. Это называется "конструкция при первом использовании"

Недостатком этого подхода является то, что объект никогда не разрушается. Есть другая техника, которая отвечает на эту проблему, но она должна использовать с осторожностью, так как это создает возможность другого неприятная) проблема.

Примечание: фиаско статического порядка инициализации также может, в некоторых случаях, применяется к встроенным / встроенным типам.

2 голосов
/ 07 сентября 2011

Первый позволяет вам удалить экземпляр, а второй нет.Но учтите, что ваш первый пример не безопасен для потоков

0 голосов
/ 07 сентября 2011

Первый тоже «ленивый» - он будет создан только тогда и только тогда, когда это необходимо.Если ваш Singleton дорогой, это, вероятно, то, что вы хотите.

Если ваш Singleton дешево и , вы можете иметь дело с неопределенным порядком статической инициализации (используйте его перед main ()), вы также можете перейти ко второму решению.

0 голосов
/ 07 сентября 2011

Шаблоны синглтонов обычно считаются плохой практикой, поэтому эмпирические данные (то, что вы «видите больше всего») в этом случае не имеют большого значения.

Первая версия использует динамическое распределение, а вторая - статическоераспределение.То есть второе распределение не может завершиться ошибкой, в то время как первое может вызвать исключение.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...