Di recente abbiamo approfondito questo argomento nella mia classe EECS. Se vuoi guardare le note della lezione in dettaglio, visita http://umich.edu/~eecs381/lecture/IdiomsDesPattsCreational.pdf
Ci sono due modi che conosco per creare correttamente una classe Singleton.
Primo modo:
Implementalo in modo simile al modo in cui lo hai nel tuo esempio. Per quanto riguarda la distruzione, "I singoli di solito durano per la durata dell'esecuzione del programma; la maggior parte dei sistemi operativi recupererà la memoria e la maggior parte delle altre risorse quando un programma termina, quindi c'è un argomento per non preoccuparsi di questo".
Tuttavia, è buona norma ripulire al termine del programma. Pertanto, è possibile farlo con una classe SingletonDestructor ausiliaria statica e dichiararlo come amico nel proprio 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; }
};
Il Singleton_destroyer verrà creato all'avvio del programma e "quando il programma termina, tutti gli oggetti globali / statici vengono distrutti dal codice di arresto della libreria di runtime (inserito dal linker), quindi il_destroyer verrà distrutto; il suo distruttore eliminerà il Singleton, eseguendo il suo distruttore."
Secondo modo
Questo si chiama Meyers Singleton, creato dal mago del C ++ Scott Meyers. Definisci semplicemente get_instance () in modo diverso. Ora puoi anche sbarazzarti della variabile membro puntatore.
// public member function
static Singleton& Singleton::get_instance()
{
static Singleton s;
return s;
}
Questo è pulito perché il valore restituito è per riferimento ed è possibile utilizzare la .
sintassi invece di ->
accedere alle variabili dei membri.
"Il compilatore crea automaticamente il codice che crea la prima volta attraverso la dichiarazione, non successivamente, e quindi elimina l'oggetto statico al termine del programma."
Si noti inoltre che con Meyers Singleton è possibile "trovarsi in una situazione molto difficile se gli oggetti si basano l'uno sull'altro al momento della terminazione - quando Singleton scompare rispetto ad altri oggetti? Ma per applicazioni semplici, funziona bene".