Leider ist der Orginalthread 'C++ Wie Dekonstruktor einsetzen? von *Markus, 15. 04. 2006, 16:26' schon im Archiv.
Da in den Antworten auf Markus' Frage eine Menge Ungenauigkeiten zu lesen sind, möchte ich ihn nochmal aufwärmen.
Das Teil heißt im Jargon 'Destruktor' und hat nichts mit dem Dekonstruktivismus zu tun. Er ist das Gegenstück zum 'Konstruktor'.
Der Destruktor einer Klasse wird immer dann aufgerufen, wenn ein Objekt des betreffenden Typs ungültig wird - egal, wo im Speicher das Objekt angelegt war.
Konstruktor und Destruktor eines Objektes sind optional.
Wenn der Programmierer keinen Konstruktor definiert hat, erzeugt der Compiler einen Default-Konstruktor.
Beispiel:
class A {
punbic:
int i;
};
Implizit wird hier folgender Konstruktor erzeugt:
A::A() { }
Das sieht auf den ersten Blick nicht sehr sinnvoll aus. Folgendes Beispiel verdeutlicht den Sinn der Sache:
class B {
int Bi;
public:
B();
};
B::B() { Bi = 4711; }
class C {
public:
B B_Komponente;
}
Für die Klasse C erzeugt der Compiler folgenden Default-Konstruktor - der Programmierer könnte ihn auch in dieser Form notiert haben:
C::C() { }
Der feine Unterschied zu A::A() ist, daß der Compiler - implizit - einen Aufruf des Konstruktors B::B() einbaut und so sicherstellt, daß Bi mit dem geforderten Wert vorbesetzt wird.
Beim Destruktor verhält es sich entsprechend: Notiert der Programmierer keinen Destruktor, wird bei Bedarf vom Compiler der passende Default-Destruktor erzeugt, der im Fall der Klasse C implizit den Destruktor B::~B() für die Komponente Bi aufruft.
Für die Klasse B bräuchte man eigentlich keinen Destruktor. Der Compiler erzeugt trotzdem zunächst die entsprechenden Default-Destruktor und der Optimierungspaß stellt dann hinterher fest, daß er nicht gebraucht werden und entfernt ihn wieder.
Daß Destruktoren jedoch in der Praxis sehr wichtig sind, zeigt das folgende Beispiel:
class D {
D *pNext;
public:
D(D *pN);
~D();
};
D::D(D *pN) { pNext = pN; }
D::~D() { delete pN; }
Wenn ein Objekt der Klasse D ungültig wird, muß dafür gesorgt werden, daß das Objekt, auf das D::pNext zeigt, ebenfalls vernichtet wird; anderenfalls entsteht ein Speicherleck: Das Objekt existiert zwar noch, ist aber nicht mehr ansprechbar.
(Nebenbei: Es entsteht ein neues Problem: Das Besitzrecht an einem Objekt. Zerstört der Destruktor ein Objekt, auf das andere Objekte oder Variablen noch verweisen, entstehen böse Probleme, die meist nicht leicht zu finden sind und das betroffene Programm äußerst instabil machen. Dieses Problem kann man nur durch sorgfältigen Programmentwurf in den Griff bekommen.)
Die vom Compiler erzeugten Default-Kon-/Destruktoren rufen nur ihre Gegenstücke für die Komponenten der Klasse auf. Varibalen, die keinem Klassentyp angehören (z.B. int oder char *) bleiben unberührt, ihr Inhalt ist undefiniert!
Beispiele, die zeigen, wann Konstruktor und Destruktor eines Objektes gerufen wird und wann nicht:
void foo(C *pCC) {
C *pc; // Kein Aufruf eines Konstruktors!
C c; // C wird lokal angelegt, der Konstruktor wird gerufen
pc = new C; // Ein Objekt vom Typ C wird auf dem Heap allokiert und der Default-Konstruktor aufgerufen
if (irgendeineBedingung) {
C c; // Ein neues C wird lokal im aktuellen Block angelegt, der Konstruktor wird gerufen
// Achtung: der Name c überdeckt hier den äußeren!!!
// ...
} // An dieser Stelle erzeugt der Compiler automatisch einen Aufruf von C::~C() für das innere c
// ...
delete pc; // Hier wird zunächst der Destruktor für das C gerufen, auf das pc zeigt
// Anschließend gibt der delete-Operator den Speicher an die Speicherverwaltung zurück
} // An dieser Stelle erzeugt der Compiler automatisch einen Aufruf von C::~C() für das (äußere) c
// Für den Parameter pCC werden von foo weder Konstruktor noch Destruktor gerufen!
Destruktoren geben dem Programmierer ein standardisiertes Schema zum abräumen von Datenstrukturen an die Hand, das diesen häufig sehr komplexen Prozeß intuitiv handhabbaren Regeln unterwirft. Üblicherweise muß man Destruktoren nicht explizit aufrufen - der Compiler besorgt das automatisch. (Seit der Standard Template Library (STL) wurde die Sprache um eine Möglichkeit des expliziten Destruktoraufrufs erweitert - benutzt man sie, wirds allerdings leicht ziemlich unübersichtlich...)
Ich hoffe, ich habe etwas Klarheit geschaffen...