Ein Destruktor (auch Finalizer genannt) ist das Gegenstück zum Konstruktor: Er wird automatisch aufgerufen, wenn ein Objekt sein Leben beendet, und gibt belegte Ressourcen wieder frei. Wo der Konstruktor den Ausgangszustand herstellt, räumt der Destruktor auf — Dateien schließen, Verbindungen beenden, Speicher freigeben.
Syntax in verschiedenen Sprachen
In C++ hat der Destruktor den Klassennamen mit vorangestellter Tilde (~) und keinen Rückgabetyp. In C# heißt er ebenfalls wie die Klasse, aber mit ~-Präfix. Java und Python kennen keine Destruktoren im klassischen Sinne: Java nutzt den finalize()-Mechanismus (inzwischen veraltet), Python die __del__-Methode — und verlässt sich ansonsten auf den Garbage Collector.
// C++: Destruktor mit Tilde
class DateiWandler {
public:
DateiWandler() { ablage = fopen("daten.txt", "w"); }
~DateiWandler() { if (ablage) fclose(ablage); } // Ressource freigeben
private:
FILE* ablage;
};
Wann wird aufgerufen?
Der Destruktor läuft, sobald das Objekt nicht mehr benötigt wird: in C++ beim Verlassen des Gültigkeitsbereichs (Stack-Semantik, siehe Stack und Heap) oder beim delete eines dynamisch erzeugten Objekts. In Python wird __del__ durch den Garbage Collector aufgerufen, sobald keine Referenzen mehr existieren — der genaue Zeitpunkt ist also nicht deterministisch. Für verlässliches Aufräumen nutzt Python deshalb das with-Statement beziehungsweise den Kontextmanager (__enter__/__exit__):
# Python: Ressourcen sauber freigeben per Kontextmanager
with open("daten.txt") as datei:
inhalt = datei.read() # Schließen passiert automatisch
Destruktor vs. Garbage Collection
Sprachen mit Garbage Collection (Java, C#, Python) entlasten den Programmierer beim Speichermanagement: Nicht mehr referenzierte Objekte werden vom Collector eingesammelt. Ressourcen wie offene Dateien oder Netzwerkverbindungen kennt der Collector aber nicht — sie müssen über explizite Freigabe (try-with-resources, using, with) oder Finalizer freigegeben werden. Sprachen ohne Garbage Collection (C, C++) verlangen diese Disziplin vom Entwickler: Jeder Pointer, der mit new erzeugt wurde, braucht irgendwann ein delete — sonst drohen Speicherlecks.
Praxis-Tipps
- Destruktoren beziehungsweise Finalizer sollten kurz und fehlerfrei sein — Ausnahmen im Aufräumcode sind besonders schwer zu diagnostizieren.
- Aufräumlogik gehört nicht in den Registrier- beziehungsweise Freigabe-Wirrwarr vieler Objekte: Ein gemeinsames Muster (RAII in C++, Kontextmanager in Python) hält den Code wartbar.
- In C++ schützt RAII (Resource Acquisition Is Initialization) vor Lecks: Die Ressource wird im Konstruktor geholt und im Destruktor freigegeben — das Objekt räumt sich selbst ab.
Zusammen mit Kapselung, Polymorphie und dem Konstruktor bildet der Destruktor den Lebenszyklus eines jeden Objekts in der Objektorientierung.