Wir haben dieses Thema kürzlich in meinem EECS-Kurs besprochen. Wenn Sie sich die Vorlesungsunterlagen im Detail ansehen möchten, besuchen Sie http://umich.edu/~eecs381/vorlesung/IdiomsDesPattsCreational.pdf . Diese Notizen (und Zitate, die ich in dieser Antwort wiedergebe) wurden von meinem Professor, David Kieras, erstellt.
Meines Wissens gibt es zwei Möglichkeiten, eine Singleton-Klasse korrekt zu erstellen.
Erster Weg:
Implementieren Sie es so, wie Sie es in Ihrem Beispiel haben. Was die Zerstörung angeht: "Singletons bestehen in der Regel für die Dauer des Programmlaufs; die meisten Betriebssysteme stellen den Speicher und die meisten anderen Ressourcen wieder her, wenn ein Programm beendet wird, also gibt es ein Argument, sich darüber keine Gedanken zu machen."
Es ist jedoch gute Praxis, bei Programmende aufzuräumen. Daher können Sie dies mit einer statischen Hilfsklasse SingletonDestructor tun und diese als Freund in Ihrem Singleton deklarieren.
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; }
};
// somewhere in code (Singleton.cpp is probably the best place)
// create a global static Singleton_destroyer object
Singleton_destoyer the_destroyer;
Der Singleton_destroyer wird beim Programmstart erstellt, und "wenn das Programm beendet wird, werden alle globalen/statischen Objekte durch den Shutdown-Code der Laufzeitbibliothek (eingefügt durch den Linker) zerstört, so dass der_destroyer zerstört wird; sein Destruktor löscht das Singleton, indem er seinen Destruktor ausführt."
Zweiter Weg
Dies wird Meyers Singleton genannt und wurde vom C++-Zauberer Scott Meyers entwickelt. Definieren Sie get_instance() einfach anders. Jetzt können Sie auch die Zeigervariable loswerden.
// public member function
static Singleton& Singleton::get_instance()
{
static Singleton s;
return s;
}
Das ist praktisch, weil der zurückgegebene Wert ein Verweis ist und Sie mit .
Syntax anstelle von ->
um auf Mitgliedsvariablen zuzugreifen.
"Der Compiler erstellt automatisch Code, der 's' beim ersten Mal durch die Deklaration erzeugt, danach nicht mehr, und löscht dann das statische Objekt bei Programmende."
Beachten Sie auch, dass Sie mit dem Meyers-Singleton "in eine sehr schwierige Situation geraten können, wenn Objekte zum Zeitpunkt der Beendigung voneinander abhängen Beendigung aufeinander angewiesen sind - wann verschwindet das Singleton im Verhältnis zu anderen Objekten? Aber für einfache Anwendungen funktioniert das gut."