Ist 'this->~T();' möglich?
-
destructor() schrieb:
PS: delete ruft doch den Destruktor des Objekts auf, so dass die Schreibweise
this->~T(); //die gleiche Semantik haben sollte wie delete this;
Achja: dieses this liegt aber wiederum im Heap.
Sollte this->~T(); also das Objekt loeschen und den Speicher im Heap genauso freigeben wie 'delete this'? Das ist jetzt meine konkrete Frage.
-
das kannst du dir sparen, Objekte auf dem Stack werden automatisch zerstoert ( und auch ihr Dtor aufgerufen), wenn das Programm ihren Gueltigkeitsbereich verlaesst.
Wenn du z. B. in einer Funktion ein Objekt auf dem Stack erstellst, wird es bei verlassen der Funktion GANZ AUTOMATISCH wieder vom Stack geloescht.
z. B.
class Foo { // ... }; void bar(); int main() { bar(); } void bar() { // in der Funktion bar wird ein Foo-Objekt erstellt Foo f; // ... // so, hier endet die Funktion bar(), und mit dem Ende von bar // wird auch der Dtor von f automatisch aufgerufen und der Speicher, // den f auf dem Stack belegt, wieder freigegeben }
Es ist NIE (zumindest kann ich mir absolut keinen solchen Fall ausdenken) noetig, den Dtor "von Hand" aufzurufen. Das wird automatisch erledigt, sobald das Objekt "stirbt" (d.h. bei einem Aufruf von delete, wenn das Objekt auf dem Heap angelegt wurde, oder bei Verlassen des Gueltigketisbereiches, wenn es auf dem Stack angelegt wurde)
-
Denke dir fuers erste den Konstruktor und Destruktor als normale Methoden.
Dann:A *a = new A(); // Speicherreservierung auf Heap + Konstruktoraufruf delete a; // Destruktoraufruf + Speicher freigeben { A a; // Speicherreservierung auf Stack + Konstruktoraufruf //(X) } // Destruktoraufruf A:~A() + Stackspeicherfreigabe
Wenn Du nun bei (X) den Destruktor aufrufst, wird er logischerweise insgesamt zweimal aufgerufen, denn der Stack schert sich nicht darum ob das Objekt schon destruiert wurde.
-
Eine Anwendung zum Aufruf des Destruktors waere z.B., wenn man ein Objekt loeschen will und ein neues erstellen will, ohne der Speicherplatz neu allokieren zu muessen.
{ A a; a.~A(); new (&a) A(); // Ruft Konstruktor auf }
(Ich hoffe die Syntax war i.O.; sowas macht man eher selten..)
-
Gunnar schrieb:
Eine Anwendung zum Aufruf des Destruktors waere z.B., wenn man ein Objekt loeschen will und ein neues erstellen will, ohne der Speicherplatz neu allokieren zu muessen.
{ A a; a.~A(); new (&a) A(); // Ruft Konstruktor auf }
(Ich hoffe die Syntax war i.O.; sowas macht man eher selten..)
1. Glaub nicht, dass das funktioniert.
2. Welchen Sinn macht das? In so einem Fall legt man das ganze doch eher auf dem Heap an, oder?
-
Doch, es kann sinnvoll sein:
T& operator=(const T& rhs) { this->~T(); // altes Objekt löschen new (this) T(rhs); // copy-ctor aufrufen return *this; }
Vorteil ist, dass die Zuweisung genauso wie Konstruktion funktioniert, wobei sich allerdings arge Probleme ergeben, wenn new fehlschlägt: Dann hat man nämlich ein uninitialisiertes Objekt am Hals, das man nicht mehr los wird... Also im Endeffekt doch nicht so sinnvoll
Ein anderer Grund ist, dass man den Speicher selber verwalten will, z.B. wie std::vector:// Platz für 5 Objekte reservieren, aber vorerst nur 2 Objekte speichern T* data = (T*)malloc(sizeof(T) * 5); new (data) T; new (data + 1) T; void push_back(const T& obj) { // Neues Objekt im Array speichern new (data + 2) T(obj); }
-
Der Tipp, ich solle "delete this" benutzen funktioniert nicht (oder es liegt an mir). Ich habe folgende Test-Klasse geschrieben, um mal auszuprobieren:
class Test { public: ~Test() { cout<<"wird aufgerufen\n"; } void destructor() { delete this; } };
Bekomme ne Debug Assertion Failed-Meldung.
Wie war das mit delete this gemeint?
-
Hallo,
den Beitrag von Tag bitte ignorieren. Was er da vorstellt ist ein absolutes Anti-Idiom und sollte niemals in einem ordentlichen C++ Programm auftauchen
(die vielen Probleme dieses Anti-Idiom werden z.B. in Herb Sutters "Exceptional C++" diskutiert).Die "richtige" Variante des op= wäre:
T& operator=(const T& other) { T temp(other); Swap(temp); return *this; }
Das drückt Copy-Assignment auch mit Hilfe von Copy-Construction aus, hat aber keines der Probleme der Anti-Idiom-Variante (kein Slicing, keine Exception-Safety-Probleme usw.).
so das man gezwungen ist (hier in einer besonderen Situation bei mir), den Destruktor explizit aufzurufen:
Es gibt nur *eine* Situation in der man gezwungen ist einen Dtor explizit aufzurufen: nämlich dann, wenn man ein Objekt per placement new angelegt hat. Eine Sache, die äußerst selten vorkommt.
Sollte this->~T(); also das Objekt loeschen und den Speicher im Heap genauso freigeben wie 'delete this'?
Nein. Ersteres ruft nur den Dtor des Objekts auf. Letzteres ruft erst den Dtor des Objekt und dann die zur new passenden operator delete-Funktion auf.
-
Hallo,
delete this ist nur ok, wenn alle hier genannten Bedingungen erfüllt sind.Mich dünkt der ein oder andere hier hat die korrekte Verwendung von C++ bisher nicht verstanden.
-
Ich hab mal ne Klasse geschrieben deren abgeleitete Klassen nur aufm Heap erstellt werden können und jederzeit mit delete this zerstört werden können, falls der Threadersteller sowas machen wollte (er hat ja nicht gesagt, was er wollte).
Hier die Klasse:
class Base { protected: virtual inline void del(){} private: inline ~Base(){} public: Base(){} virtual void destroy(){del(); delete this;} friend void* operator new(size_t); friend void operator delete(void*, size_t); };
Ich hab noch festgestellt, dass man den Destruktor der abgeleiteten Klassen überhaupt nicht erwähnen sollte, sondern alles in die Funktion del() packen sollte.
mfg Glamdring
-
Hallo,
du solltest deinen Dtor dringend virtual machen.
-
Ich habe doch geschrieben, dass der angesprochene operator= nicht gut ist...
(die vielen Probleme dieses Anti-Idiom werden z.B. in Herb Sutters "Exceptional C++" diskutiert).
Rate mal, woher dieses "doch nicht so sinnvoll"e Anti-Beispiel stammt
-
tag schrieb:
Ich habe doch geschrieben, dass der angesprochene operator= nicht gut ist...
Mir war dein Hinweis ehrlich gesagt zu "kleingedruckt"
Deshalb wollte ich das noch mal etwas expliziter machen.
-
HumeSikkins schrieb:
Mir war dein Hinweis ehrlich gesagt zu "kleingedruckt"
Na gut, das sehe ich ein
-
@Hume: Nee, dann könnten abgeleitete Klassen ihrer Destruktor auch public machen und müssten nicht unbedingt auf dem Heap erzeugt werden. Die Funktion del ist in dem Fall der Pseudo-Destruktor, wenn also ein Pointer drinn ist schreibst du:
virtual void Derrived::del() { delete Pointer; }
Dadurch ist kein Speicherloch entstanden