Repasamos este tema recientemente en mi clase de EECS. Si desea ver las notas de clase en detalle, visite http://umich.edu/~eecs381/lecture/IdiomsDesPattsCreational.pdf
Hay dos maneras en que sé crear una clase Singleton correctamente.
Primera forma:
Impleméntelo de forma similar a como lo tiene en su ejemplo. En cuanto a la destrucción, "los Singletons generalmente perduran durante la ejecución del programa; la mayoría de los sistemas operativos recuperarán la memoria y la mayoría de los otros recursos cuando finalice un programa, por lo que hay un argumento para no preocuparse por esto".
Sin embargo, es una buena práctica limpiar al finalizar el programa. Por lo tanto, puede hacer esto con una clase auxiliar SingletonDestructor estática auxiliar y declarar eso como amigo en su Singleton.
class Singleton {
public:
static Singleton* get_instance();
// disable copy/move -- this is a Singleton
Singleton(const Singleton&) = delete;
Singleton(Singleton&&) = delete;
Singleton& operator=(const Singleton&) = delete;
Singleton& operator=(Singleton&&) = delete;
friend class Singleton_destroyer;
private:
Singleton(); // no one else can create one
~Singleton(); // prevent accidental deletion
static Singleton* ptr;
};
// auxiliary static object for destroying the memory of Singleton
class Singleton_destroyer {
public:
~Singleton_destroyer { delete Singleton::ptr; }
};
Singleton_destroyer se creará al inicio del programa, y "cuando el programa finaliza, todos los objetos globales / estáticos son destruidos por el código de apagado de la biblioteca en tiempo de ejecución (insertado por el enlazador), por lo que el destructor eliminará el Singleton, ejecutando su incinerador de basuras."
Segunda forma
Esto se llama Meyers Singleton, creado por el asistente de C ++ Scott Meyers. Simplemente defina get_instance () de manera diferente. Ahora también puede deshacerse de la variable miembro del puntero.
// public member function
static Singleton& Singleton::get_instance()
{
static Singleton s;
return s;
}
Esto es correcto porque el valor devuelto es por referencia y puede usar la .
sintaxis en lugar de->
acceder a las variables miembro.
"El compilador crea automáticamente el código que crea 's' por primera vez a través de la declaración, no después, y luego elimina el objeto estático al finalizar el programa".
Tenga en cuenta también que con el Singleton de Meyers "puede entrar en una situación muy difícil si los objetos dependen unos de otros en el momento de la terminación: ¿cuándo desaparece el Singleton en relación con otros objetos? Pero para aplicaciones simples, esto funciona bien".