Singleton Lebenszeit
-
@2: Statische (dazu gehört auch der Meyers Singleton) und globale Variablen werden in der umgekehrten Reihenfolge gelöscht, in der sie erzeugt wurden.
PS: Ein kleiner Tip vom Mod - bitte keine Themen kapern, noch dazu mit themenfremden Fragen.
-
Alexandrescu hat in Modern C++ Design ein gutes Kapitel zu genau diesem Thema.
-
Ok, mein konkretes Problem ist das:
Ich habe mehrere Singleton Klassen. Die wichtigsten sind eine App Klasse A und ein Logger L. Die App benutzt den Logger, d.h. man kann davon ausgehen, dass die Konstruktionsreihenfolge A, L ist. D.h. also, dass wenn ich das Singleton Design mit einer statischen lokalen Variablen mach, dass L vor A zerstört wird und ich im Dtor von A NICHT loggen kann, richtig?
Wäre es dann nicht die einfachste Lösung, wenn ich ein Hauptsingleton (App) habe, dass die Lebenszeit aller andren Singletons kontrolliert?
Quasi so:// Main Singleton class App { private: App(); ~App(const App& rhs); App& operator=(const App& rhs); static App* instance; public: App& createInstance() { if(instance == NULL) instance = new App(); return *instance; } App& getInstance() { assert(instance); return *instance;´ } void destroyInstance() { if(instance) delete instance; } App() { // Andere Singletons erzeugen: Logger::createInstance("MyLogger"); MemoryManager::createInstance(); ... } ~App() { // Andere Singletons zerstören: Logger::destroyInstance(); MemoryManager::destroyInstance(); ... };Die Benutzung ist dann:
int main() { App& a = App::createInstance(); Ab jetzt ist App und alle anderen Singletons benutzbar a.foo(); ... App::destroyInstance(); }Sieht das ok aus? Ist das ein guter Ansatz? PS: Ich benutze KEIN Multithreading.
-
Singletonner schrieb:
Die Benutzung ist dann:
int main() { App& a = App::createInstance(); Ab jetzt ist App und alle anderen Singletons benutzbarNö. Der Logger muß freier sein.
Wegenstruct BigLUT{ std::map<std::string,std::string>; BigLUT(){ ifstream in(... ... }try(std::exception ex){ Logger::createInstance("MyLogger")<<"Critical Error: "<<ex.what()<<endl; }; }; BitLUT theOneAndOnlyBigLUT;oder beliebig anderem Code, der vor der main ausgeführt wird.
-
@volkard
Irgendwas ist mit deinem try {} ... catch () {} schief gelaufen.
-
Es gibt vor main keinen Code.
-
Edit: gelöscht
-
Singletonner schrieb:
Es gibt vor main keinen Code.
Doch, z. B. alle statischen freien Variablen. Sieh dir mal volkards Code an.
Edit: Ach, du bist der OP. Meinst du damit, dass in deinem konkreten Fall kein Code vor main ausgeführt wird?
-
Michael E. schrieb:
Edit: Ach, du bist der OP. Meinst du damit, dass in deinem konkreten Fall kein Code vor main ausgeführt wird?
Ja, genau das wollte ich damit sagen^^
Ich habe in meinem Programm keine globalen Objekte, also auch keinen Code vor main.
Ich finde meinen Ansatz mit dem Singleton "Manager" eigentlich ganz gut. Ich weiß genau wann alle Singletons erzeugt und zerstört werden.
-
App() { Logger::createInstance("MyLogger"); ... }Führt eigentlich direkt zu
BigLUT(){ Logger::createInstance("MyLogger"); ifstream in(... ... } App() { Logger::createInstance("MyLogger"); ... }Hmm, das könnte zyklisch werden. Angst hab.
-
Ich hab keine Ahnung was du meinst. Und was soll dieses BigLUT sein?
-
Singletonner schrieb:
Und was soll dieses BigLUT sein?
Das wollte ich wissen. Du mußt Alexandrescu lesen.
-
Gibt es diesen Singleton Alexandrescu Artikel irgendwo online? Ich finde ihn nirgends...
Ich habe mein Design jetzt etwas geändert. Meine App Klasse ist mittlerweile kein Singleton mehr. Man kann nach wie vor zwar nur 1 Instanz von ihr Erzeugen:
App* a = A::createInstance(); a->foo(); ... // wenn fertig: delete a;aber es gibt keine globalen statischen Zugriffsfunktionen.
Meine anderen Klassen wie Logger sind Meyer Singletons (also mit lokalen statischen Variablen).
Frühestens im App Ctor benutze ich zum 1. Mal die Singletons:App::App() { Logger::getInstance().log("App created."); }Wenn ich jetzt meine App erzeuge und kurz vor Programmende wieder lösche (delete app), dann kann ich doch im App Dtor noch die Singletons benutzen, oder?
-
Hallo,
Hier sind mal zwei Artikel zu Singletons.
http://www.devarticles.com/c/a/Cplusplus/C-plus-plus-In-Theory-The-Singleton-Pattern-Part-I/
http://www.devarticles.com/c/a/Cplusplus/C-plus-plus-In-Theory-The-Singleton-Pattern-Part-2/
-
singletonner schrieb:
Wenn ich jetzt meine App erzeuge und kurz vor Programmende wieder lösche (delete app), dann kann ich doch im App Dtor noch die Singletons benutzen, oder?
Eine Klasse ist erst dann "erstellt" wenn der Konstruktor komplett durchgelaufen ist. Daraus folgt das wenn Die Klasse B innerhalb der Konstruktors von A erzeugt wird, diese Klasse B vor A erzeugt wurde. Daraus folgt wieder das der Destruktor von B nach dem Destruktor von A aufgerufen wird (umgekehrte Reihenfolge zur Konstruktion). Also ist die Annahme richtig.
Will man da auf 100% sicher gehen, könnte man das über einen Smartpointer zusätzlich absichern. Über eine virtuelle Basisklasse wäre es da sogar möglich das Logging zur Laufzeit zu ändern. Ein Mechanismus der manchmal notwendig ist wenn das Logginginterface ständig zur Verfügung stehen muss, das eigentliche Logging aber vom Framework abhängig ist und nicht über die ganze Laufzeit des Programms funktioniert.