Objekte erzeugen auf dem Stack oder auf dem Heap ?
-
Also mit sizeof( X ) bekomme ich "4" zurück geliefert, habe aber min. 8 int in dem Objekt.
Kannst du das mit dem Singleton etwas näher erläutern ?
Danke und Gruß
WoWe
-
sizeof( *Zeiger )
-
Danke,
damit sieht der Wert realistisch aus.
Kannst du auch was zu Singleton und meinem Beispiel sagen ?
-
WoWe schrieb:
Kannst du auch was zu Singleton und meinem Beispiel sagen ?
CKlasse& getTheOneAndOnlyCKlasse(){ static CKlasse x; return x; } //und wer es braucht, macht getTheOneAndOnlyCKlasse().methode();das objekt wird erst angelegt, wenn es zum ersten mal gebaraucht wird und wird automagisch nach der main() gelöscht.
-
Hallo Volkard,
danke für deine Hilfe. Das bringt mich zwar i.M. noch nicht weiter, aber ich hab zumindst was zum Googlen

-
WoWe schrieb:
Hallo Volkard,
danke für deine Hilfe. Das bringt mich zwar i.M. noch nicht weiter, aber ich hab zumindst was zum Googlen

dann google gleich nach meyers-singleton
der meyers-singleton ist der gebräuchlichste, aber es gibt noch nen haufen mehr. wenn du den kennst und der nicht so passt, sag genau, was du brauchst, dann frickeln wir einen zusammen.
-
Hallo volkard,
Was gibt es denn noch für Singletons?
Ist Meyers-Singleton threadsicher oder kann da theoretisch
(natürlich nur beim 1. Aufruf) Konflikte entstehen?Gruß,
Dennis
-
Singleton schrieb:
Hallo volkard,
Was gibt es denn noch für Singletons?nen ganzen haufen hat alexandrescu in modern c++ design gezeigt.
Ist Meyers-Singleton threadsicher oder kann da theoretisch
(natürlich nur beim 1. Aufruf) Konflikte entstehen?da kann ein konflikt entstehen.
natürlich kann man den wiederum mit men mutex abfangen. und den mutex verbilligt man mit nem atomaren nachguck auf nen int um den mutex. oder man tutu threadlokal die referenz auf das objekt cachen. oder, was mein liebling ist, man erzwingt die erzeugung einfach vorher mitnamepace{ CKlasse& theOneAndOnlyCKlasse=getTheOneAndOnlyCKlasse(); }innerhalb der Klasse.h
-
Oder man macht kein meyers-singleton, sondern so:
class CKlasse { private: CKlasse() { } ~CKlasse() { } CKlasse& operator= (const CKlasse&) { } public: static CKlasse& getInstance(); }; CKlasse& getInstance() { static CKlasse* instance = 0; static Mutex mutex; if (instance == 0) // erst ohne lock prüfen { Lock lock(mutex); if (instance == 0) // jetzt mit lock prüfen, ob sich inzwischen was geändert hat { // hier sind wir jetzt exklusiv instance = new CKlasse(); } } return *instance; }Das minimiert die Locks und man hat selbst Kontrolle über die Instantiierung. Ist bei Alexandrescu beschrieben.
Die ganze Sache mit dem privaten Konstruktor, Destruktor und Zweisungsoperator hat den Sinn, daß der Compiler schon meckert, wenn man versucht, eine Instanz selbst anzulegen. Das kann schon mal versehentlich passieren, wie z. B.:
CKlasse instanz = CKlasse::getInstance(); // geht nicht, da Zuweisung privat istso geht es aber:
CKlasse& instanz = CKlasse::getInstance();Ein Nachteil hat das ganze: Die Klasse wird nie zerstört. Aber das will man ja eigentlich auch gar nicht. Das fällt aber auf, wenn man einen Memory-leak-debugger nutzt. Der bemängelt, daß die Instanz nach Programmende nicht freigegeben wurde.
Tntnet
-
tntnet schrieb:
Oder man macht kein meyers-singleton, sondern so:
Das minimiert die Locks und man hat selbst Kontrolle über die Instantiierung. Ist bei Alexandrescu beschrieben.
Die ganze Sache mit dem privaten Konstruktor, Destruktor und Zweisungsoperator hat den Sinn, daß der Compiler schon meckert, wenn man versucht, eine Instanz selbst anzulegen. Das kann schon mal versehentlich passieren, wie z. B.:
CKlasse instanz = CKlasse::getInstance(); // geht nicht, da Zuweisung privat istso geht es aber:
CKlasse& instanz = CKlasse::getInstance();Ein Nachteil hat das ganze: Die Klasse wird nie zerstört. Aber das will man ja eigentlich auch gar nicht. Das fällt aber auf, wenn man einen Memory-leak-debugger nutzt. Der bemängelt, daß die Instanz nach Programmende nicht freigegeben wurde.
Tntnet
leider ist auch das nicht thread-safe. der zeiger instance sollte auf jeden fall extern linkage haben. nur dann kann man argumentieren, dass das erstellen eines Lock objekts potentiell auswirkungen auf seinen zustand hat (und so den compiler daran hindern, den code so zu transformieren, dass etwa das zweite if vor dem lock steht). das andere - wesentlichere - problem ist die sichtbarkeit von veränderungen an instance. ohne ein geeignetes speichermodell, das C++ gegnwärtig nicht hat, ist dieses problem prinzipiell nicht allgemein lösbar. die tatsache, das so etwas auf single-prozessor-systemen oder typischen multicore-pc-systmen funktioniert, bedeutet nicht, das diese konstruktion an sich sicher ist.
Edit: es müßte genügen, instance volatile zu machen, anstatt ihm extern linkage zu geben. zwar ist der einzige weg, auf instance zuzugreifen, der aufruf von getInstance(), aber genau das könnte der Lock-Konstruktor ja tun. und da zugriffe auf volatile variablen und die reihenfolge dieser zugriffe beobachtbar sind; genügt das, um die beschriebene umordnung zu verhindern (vorausgesetzt, der compiler bekommt bestimmte teile des codes von Lock nie zu sehen). Ein anderes problem ist Mutex. Da es sich vermutlich nicht um ein POD handelt, wird der compiler die initialisierung erst beim ersten aufruf initialisieren. aber wann ist denn der erste aufruf, wenn die funktion aus mehreren threads aufgerufen wird ?
