Подтвердить что ты не робот

С++ singleton против глобального статического объекта

Мой друг сегодня спросил меня, почему он предпочитает использовать одноэлемент над глобальным статическим объектом? То, как я начал объяснять, было то, что у синглтона может быть состояние против статического глобального объекта, но не было... но тогда я не был уверен... потому что это в С++.. (я шел из С#)

Каковы преимущества одного над другим? (в С++)

4b9b3361

Ответ 1

Собственно, в С++ предпочтительным способом является локальный статический объект.

Printer & thePrinter() {
    static Printer printer;
    return printer;
}

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

Что делает его лучше, чем обычный способ делать одиночные игры с созданием нового экземпляра, вызывая new, так это то, что объект-деструктор объекта будет вызываться в конце программы. Это не произойдет с динамически выделяемым синглетоном.

Еще одна положительная сторона - нет способа получить доступ к синглтону до его создания, даже из других статических методов или из подклассов. Сохраняет время отладки.

Ответ 2

В С++ порядок экземпляра статических объектов в разных единицах компиляции undefined. Таким образом, один глобальный может ссылаться на другой, который не построен, раздувая вашу программу. Шаблон singleton устраняет эту проблему, связывая конструкцию со статической функцией-членом или свободной функцией.

Здесь есть достойное резюме .

Ответ 3

Мой друг сегодня спросил меня, почему он предпочитает использовать одноэлемент над глобальным статическим объектом? То, как я начал объяснять, было то, что у синглтона может быть состояние против статического глобального объекта, но не было... но тогда я не был уверен... потому что это в С++.. (я шел из С#)

Статический глобальный объект также может иметь состояние в С#:

class myclass {
 // can have state
 // ...
 public static myclass m = new myclass(); // globally accessible static instance, which can have state
}

Каковы преимущества одного над другим? (в С++)

Синтаксис искажает ваш код, а глобальный статический экземпляр - нет. Есть бесчисленные вопросы о SO о проблемах с синглтонами уже. Здесь один, и еще один, или другой.

Короче говоря, синглтон дает вам две вещи:

  • глобально доступный объект и
  • гарантировать, что может быть создан только один экземпляр.

Если мы хотим только первую точку, мы должны создать глобально доступный объект. И почему мы когда-нибудь захотим второго? Мы не знаем заранее, как наш код может быть использован в будущем, так зачем же гвоздь его и удалить, что может быть полезной функциональностью? Обычно мы ошибаемся, когда мы прогнозируем, что "мне нужен только один экземпляр". И там большая разница между "Мне нужен только один экземпляр" (правильный ответ - создать один экземпляр), и "приложение ни при каких обстоятельствах не может работать правильно, если создано несколько экземпляров, отформатируйте жесткий диск пользователя и публикуйте конфиденциальные данные в Интернете" (ответ здесь: Скорее всего, ваше приложение сломано, но если это не так, то да, один сингл - то, что вам нужно)

Ответ 4

Причина 1:
Синглтоны легко сделать так, что они ленивы. Хотя вы можете сделать это с помощью глобальных вычислений, разработчику требуется дополнительная работа. Поэтому по умолчанию глобальные переменные всегда инициализируются (кроме некоторых специальных правил с пространствами имен).

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

Причина 2:
Порядок инициализации (и уничтожения).

GlobalRes& getGlobalRes()
{
    static GlobalRes instance;  // Lazily initialized.
    return instance;
}


GlobalResTwo& getGlobalResTwo()
{
    static GlobalResTwo instance;  // Lazy again.
    return instance;
}


// Order of destruction problem.
// The destructor of this object uses another global object so
// the order of destruction is important.
class GlobalResTwo
{
    public:
        GlobalResTwo()
        {
            getGlobalRes();
            // At this point globalRes is fully initialized.
            // Because it is fully initialized before this object it will be destroyed
            // after this object is destroyed (Guaranteed)
        }
        ~GlobalResTwo()
        {
            // It is safe to use globalRes because we know it will not be destroyed
            // before this object.
            getGlobalRes().doStuff();
        }
};

Ответ 6

Еще одно преимущество Singleton над глобальным статическим объектом заключается в том, что, поскольку конструктор является закрытым, существует очень ясная, принудительная директива компилятора, в которой говорится: "Может быть только один".

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

Преимущество дополнительного ограничения заключается в том, что у вас есть гарантия относительно того, как будет использоваться этот объект.

Ответ 7

В С++ не существует огромной разницы между двумя с точки зрения реальной полезности. Конечно, глобальный объект может поддерживать свое собственное состояние (возможно, с другими глобальными переменными, хотя я не рекомендую его). Если вы собираетесь использовать глобальный или синглтон (и есть много причин не делать этого), самая большая причина использовать одноэлемент над глобальным объектом заключается в том, что с помощью singleton вы можете иметь динамический полиморфизм, имея несколько классов, наследующих от базовый класс singleton.

Ответ 8

Хорошо, есть две причины, чтобы пойти с синглом на самом деле. Один из них - это статический порядок, о котором все говорят.

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

CoolThing blah;
gs_coolGlobalStaticThing = blah;

или, что еще хуже:

gs_coolGlobalStaticThing = {};

Аспект инкапсуляции защитит ваш экземпляр от идиотов и злобных рывков.