usar singletons plantilla patron genetica ejercicios ejemplos diseño cuando c++ static singleton global-variables

singletons - C++ singleton vs. objeto estático global



plantilla singleton (8)

Un amigo mío de hoy me preguntó por qué debería preferir el uso de singleton sobre un objeto estático global. La forma en que lo comencé a explicar fue que el singleton puede tener un estado global vs. un objeto estático no ... pero no estaba seguro ... porque esto en C ++ ... (venía de C #)

Un objeto global estático también puede tener estado en C #:

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

¿Cuáles son las ventajas una sobre la otra? (en C ++)

Un singleton invalida su código, una instancia estática global no lo hace. Hay innumerables preguntas sobre SO acerca de los problemas con singletons ya. Aquí está uno , y otro , u otro .

En resumen, un singleton te da dos cosas:

  • un objeto accesible globalmente, y
  • una garantía de que solo se puede crear una instancia.

Si queremos solo el primer punto, debemos crear un objeto accesible globalmente. ¿ Y por qué querríamos el segundo? No sabemos de antemano cómo se puede usar nuestro código en el futuro, así que, ¿por qué definirlo y eliminar lo que podría ser una funcionalidad útil? Normalmente nos equivocamos cuando predecimos que "solo necesitaré una instancia". Y hay una gran diferencia entre "Sólo necesitaré una instancia" (la respuesta correcta es crear una instancia) y "la aplicación no puede ejecutarse correctamente en ningún caso si se crea más de una instancia. Se bloqueará, formatee el disco duro del usuario y publique datos confidenciales en Internet "(la respuesta aquí es entonces: lo más probable es que su aplicación esté dañada, pero si no lo está, entonces sí, un singleton es lo que necesita)

Un amigo mío de hoy me preguntó por qué debería preferir el uso de singleton sobre un objeto estático global. La forma en que lo comencé a explicar fue que el singleton puede tener un estado global vs. un objeto estático no ... pero no estaba seguro ... porque esto en C ++ ... (venía de C #)

¿Cuáles son las ventajas una sobre la otra? (en C ++)


En C ++, el orden de creación de instancias de objetos estáticos en diferentes unidades de compilación no está definido. Por lo tanto, es posible que un global haga referencia a otro que no esté construido, explotando su programa. El patrón de singleton elimina este problema al vincular la construcción con una función miembro estática o función libre.

Hay un resumen decente here .


En C ++, no hay una gran cantidad de diferencia entre los dos en términos de utilidad real. Por supuesto, un objeto global puede mantener su propio estado (posiblemente con otras variables globales, aunque no lo recomiendo). Si va a usar un global o un singleton (y hay muchas razones para no hacerlo), el mayor motivo para usar un singleton sobre un objeto global es que con un singleton, puede tener un polimorfismo dinámico al tener varias clases heredadas de una clase base de singleton.


En realidad, en C ++ la forma preferida es el objeto estático local.

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

Esto es técnicamente un singleton, sin embargo, esta función puede ser incluso un método estático de una clase. Por lo tanto, se garantiza que se construya antes de ser utilizado a diferencia de los objetos estáticos globales, que se pueden crear en cualquier orden, lo que hace posible fallar de manera inconsistente cuando un objeto global usa otro, un escenario bastante común.

Lo que lo hace mejor que la forma común de hacer singletons con la creación de una nueva instancia llamando a new es que se llamará al destructor de objetos al final de un programa. No sucederá con singleton asignado dinámicamente.

Otro aspecto positivo es que no hay forma de acceder a singleton antes de que se cree, incluso desde otros métodos estáticos o desde subclases. Te ahorra tiempo de depuración.


OK, hay dos razones para ir con un singleton realmente. Uno es el orden estático del que todos están hablando.

La otra es evitar que alguien haga algo como esto cuando usa su código:

CoolThing blah; gs_coolGlobalStaticThing = blah;

o, peor aún:

gs_coolGlobalStaticThing = {};

El aspecto de encapsulación protegerá su instancia de idiotas y idiotas maliciosos.


Otro beneficio del Singleton sobre el objeto estático global es que debido a que el constructor es privado, hay una directiva muy clara y compilada que dice "Sólo puede haber uno".

En comparación, con el objeto estático global, no habrá nada que impida que un desarrollador escriba un código que cree una instancia adicional de este objeto.

El beneficio de la restricción adicional es que tiene una garantía de cómo se utilizará el objeto.


Razón 1:
Los singletons son fáciles de hacer, por lo que son perezosos.
Si bien puede hacer esto con globales, el desarrollador necesita más trabajo. Por lo tanto, de forma predeterminada, las variables globales siempre se inicializan (aparte de algunas reglas especiales con espacios de nombres).

Por lo tanto, si su objeto es grande y / o costoso de construir, es posible que no desee hacerlo a menos que realmente tenga que usarlo.

Razón 2:
Orden de inicialización (y destrucción) del problema.

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(); } };


Usando el lenguaje Singleton ("construir en el primer uso"), puede evitar here