Analisamos esse tópico recentemente na minha classe EECS. Se você quiser ver as notas da aula em detalhes, visite http://umich.edu/~eecs381/lecture/IdiomsDesPattsCreational.pdf
Existem duas maneiras de criar uma classe Singleton corretamente.
Primeira maneira:
Implemente de maneira semelhante à do seu exemplo. Quanto à destruição, "os singletons geralmente perduram pela duração da execução do programa; a maioria dos sistemas operacionais recupera memória e a maioria dos outros recursos quando um programa é finalizado; portanto, há um argumento para não se preocupar com isso".
No entanto, é uma boa prática limpar no final do programa. Portanto, você pode fazer isso com uma classe SingletonDestructor estática auxiliar e declarar isso como amigo no seu 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; }
};
O Singleton_destroyer será criado na inicialização do programa e "quando o programa terminar, todos os objetos globais / estáticos serão destruídos pelo código de desligamento da biblioteca de tempo de execução (inserido pelo vinculador); portanto, o_destroyer será destruído; seu destruidor excluirá o Singleton, executando seu destruidor."
Segunda Via
Isso é chamado de Meyers Singleton, criado pelo assistente de C ++, Scott Meyers. Simplesmente defina get_instance () de maneira diferente. Agora você também pode se livrar da variável de membro do ponteiro.
// public member function
static Singleton& Singleton::get_instance()
{
static Singleton s;
return s;
}
Isso é legal porque o valor retornado é por referência e você pode usar a .
sintaxe em vez de ->
acessar variáveis de membro.
"O compilador cria automaticamente o código que cria 's' pela primeira vez através da declaração, e não depois e exclui o objeto estático na finalização do programa."
Observe também que, com o Meyers Singleton, "você pode entrar em uma situação muito difícil se os objetos confiarem um no outro no momento do término - quando o Singleton desaparece em relação a outros objetos? Mas, para aplicativos simples, isso funciona bem".