Ich habe eine, class A
die eine Heap-Speicherzuordnung für eines ihrer Felder verwendet. Klasse A wird instanziiert und als Zeigerfeld in einer anderen Klasse gespeichert ( class B
.
Wenn ich mit einem Objekt der Klasse B fertig bin, rufe ich auf delete
, von dem ich annehme, dass es den Destruktor aufruft ... Aber ruft dies auch den Destruktor der Klasse A auf?
Bearbeiten:
Aus den Antworten nehme ich das (bitte bearbeiten, wenn falsch):
delete
einer Instanz von B ruft B :: ~ B () auf;- was anruft
A::~A();
A::~A
sollte explizitdelete
alle Heap-zugewiesenen Mitgliedsvariablen des A-Objekts enthalten;- Schließlich wird der Speicherblock, in dem die Instanz der Klasse B gespeichert ist, an den Heap zurückgegeben. Wenn new verwendet wurde, hat er zuerst einen Speicherblock auf dem Heap zugewiesen und dann Konstruktoren aufgerufen, um ihn zu initialisieren, nachdem alle Destruktoren aufgerufen wurden, um das Objekt zu finalisieren Block, in dem sich das Objekt befand, wird an den Heap zurückgegeben.
quelle
++
Operator verwenden. Ich frage mich also, ob ein Zeiger, der in die Mitte der Klassendaten zeigt, noch den Effekt hat.Wenn Sie delete für einen von new zugewiesenen Zeiger aufrufen, wird der Destruktor des Objekts aufgerufen, auf das verwiesen wird.
quelle
Es heißt "Destruktor", nicht "Dekonstruktor".
Innerhalb des Destruktors jeder Klasse müssen Sie alle anderen Mitgliedsvariablen löschen, denen new zugewiesen wurde.
bearbeiten: Zur Verdeutlichung:
Sagen Sie, Sie haben
Das Zuweisen einer Instanz von B und das anschließende Löschen ist sauber, da das, was B intern zuweist, auch im Destruktor gelöscht wird.
Instanzen der Klasse C verlieren jedoch Speicher, da sie eine Instanz von A zuweisen, die sie nicht freigibt (in diesem Fall hat C nicht einmal einen Destruktor).
quelle
Wenn Sie einen üblichen Zeiger (
A*
) haben, wird der Destruktor nicht aufgerufen (undA
beispielsweise wird auch kein Speicher freigegeben), es sei denn, Sie tun diesdelete
explizit imB
Destruktor. Wenn Sie automatische Zerstörung wollen, schauen Sie sich intelligente Zeiger wie anauto_ptr
.quelle
Sie sollten A selbst im Destruktor von B löschen.
quelle
Wenn Sie das tun:
Der Destruktor wird nur aufgerufen, wenn Ihre Basisklasse das virtuelle Schlüsselwort hat.
Wenn Sie dann keinen virtuellen Destruktor hätten, würde nur ~ B () aufgerufen. Da Sie jedoch einen virtuellen Destruktor haben, wird zuerst ~ D () und dann ~ B () aufgerufen.
Auf dem Heap zugewiesene Mitglieder von B oder D werden nicht freigegeben, es sei denn, Sie löschen sie ausdrücklich. Wenn Sie sie löschen, wird auch ihr Destruktor aufgerufen.
quelle
Du hast so etwas wie
Wenn Sie dann anrufen
delete b;
, passiert nichts mit a und Sie haben einen Speicherverlust. Der Versuch, sich daran zu erinnern,delete b->a;
ist keine gute Lösung, aber es gibt noch einige andere.Dies ist ein Destruktor für B, der a löscht. (Wenn a 0 ist, bewirkt dieses Löschen nichts. Wenn a nicht 0 ist, aber nicht auf den Speicher von new verweist, wird der Heap beschädigt.)
Auf diese Weise haben Sie a nicht als Zeiger, sondern ein auto_ptr <> (shared_ptr <> oder andere intelligente Zeiger) und es wird automatisch gelöscht, wenn b ist.
Jede dieser Möglichkeiten funktioniert gut, und ich habe beide verwendet.
quelle
Ich fragte mich, warum der Zerstörer meiner Klasse nicht gerufen wurde. Der Grund war, dass ich vergessen hatte, die Definition dieser Klasse aufzunehmen (#include "class.h"). Ich hatte nur eine Erklärung wie "Klasse A"; und der Compiler war damit zufrieden und ließ mich "löschen" nennen.
quelle
Nein, der Zeiger wird gelöscht. Sie sollten das Löschen auf A explizit im Destruktor von B aufrufen.
quelle
Der Destruktor für das Objekt der Klasse A wird nur aufgerufen, wenn für dieses Objekt delete aufgerufen wird. Stellen Sie sicher, dass Sie diesen Zeiger im Destruktor der Klasse B löschen.
Weitere Informationen darüber, was passiert, wenn ein Objekt gelöscht wird, finden Sie unter: http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.9
quelle
Nein, es wird kein Destruktor für Klasse A aufgerufen. Sie sollten ihn explizit aufrufen (wie PoweRoy sagte). Löschen Sie die Zeile 'delete ptr;' im Beispiel zu vergleichen ...
quelle