![]() |
Wann Destruktor-Aufruf nötig?
Hi!
In welchen Fällen ist es eigentlich sinnvoll, den Destruktor aufzurufen? Wenn ich z.B. eine Instanz beim Programmstart per FInstanz := TKlasse.Create; erzeugt habe und den Konstruktor später nochmal aufrufen möchte, um alle Eigenschaften der Instanz zurückzusetzen, ist es dann nötig, vorher die alte Instanz zu destroyen? Wann ist der Aufruf von FInstanz.Destroy überhaupt angebracht? Nur beim Programmende? |
Re: Wann Destruktor-Aufruf nötig?
Hallo,
1. schreibe eine Methode Clear, die du sowohl im constructor als auch bei Bedarf aufrufen kannst. 2. rufe nie Destroy direkt auf, sondern nimm Free. Mit Clear brauchst du erst am Programmende Free aufrufen. Heiko |
Re: Wann Destruktor-Aufruf nötig?
Zitat:
Zitat:
|
Re: Wann Destruktor-Aufruf nötig?
Warum zerstört Delphi eigentlich nicht automatisch alles am Programmende?
|
Re: Wann Destruktor-Aufruf nötig?
Du stellst dir das etwas zu einfach vor, dafür bräuchte Delphi schon einen richtigen (naja, > 3/4) Garbage Collector. Und außer bei Klassen, die ein Handle auf externe Ressourcen halten, ist das Freigeben bei Programmende sowieso egal.
|
Re: Wann Destruktor-Aufruf nötig?
Jop, um Khabarakhs Äußerung ein wenig zu präzisieren, Windows markiert Speicher, den ein Programm gehalten hatte, wieder als frei, wenn das Programm beendet wird.
|
Re: Wann Destruktor-Aufruf nötig?
Dann sind Meinungen wie "jede Klasse braucht einen Destruktor" doch eigentlich Quatsch. Bei Klassen, die das ganze Programm über gebraucht werden, ist es doch dann meistens unnötig, überhaupt einen zu deklarieren, oder?
|
Re: Wann Destruktor-Aufruf nötig?
Eine Klasse weiß nicht, wie lange sie gebraucht wird(OOP). Sie sollte deshalb alles, was sie alloziiert, auch wieder freigeben. Das ist guter Stil.
Und Pauschalaussagen sind zwar meist kein "Quatsch", aber es gibt trotzdem immer Ausnahmen ;) PS: Schon TObject hat einen Destruktor. EIne Klasse ohne Destruktor gibts also gar nicht :stupid: |
Re: Wann Destruktor-Aufruf nötig?
Zitat:
|
Re: Wann Destruktor-Aufruf nötig?
Zitat:
Ein anderer Punkt ist, wenn man später mal feststellt, dass die Klasse doch besser von einer anderen Erben soll. In diesem Fall kann ein fehlender inherited Create Aufruf zu Problemen führen. |
Re: Wann Destruktor-Aufruf nötig?
Hallo,
ich schreibe immer einen constructor, auch wenn der nur inherited Create aufruft. 1. jede Klasse wird mal erweitert 2. weit wichtiger, da ich memcheck benutze, zeigt er mir genau die Stelle, wo die Klasse erzeugt wird, aber nicht mehr freigegeben wird. 3. siehe oben (das mit der neuen Basisklasse) Heiko |
Re: Wann Destruktor-Aufruf nötig?
Nun hab ich das Problem, dass beim Zurücksetzen der Eigenschaften einige Instanzen bereits zerstört sind, andere nicht. Dann funktioniert eine Methode wie Clear natürlich nicht. Sollte ich dann doch alle Objekte wieder neu erstellen? Hab ich Beitrag #3 richtig verstanden, dass ich vor dem erneuten Create nicht erst Destroy aufzurufen brauche?
|
Re: Wann Destruktor-Aufruf nötig?
Zitat:
Zitat:
Delphi-Quellcode:
Warum sollte man nun trotzdem Speicher freigeben, auch, wenn der Speichermanager hinterher wieder aufräumt? Ganz einfach: Du kippst doch auch nicht deinen Mülleimer aus dem Fenster, nur, weil du weißt, dass irgendwann jemand kommt, der das aufräumt... Es ist einfach schlechter Programmierstil.
constructor TTest.Create;
begin inherited Create; FFeld := wert; ... FStringList := TStringList.Create; // <-- ... end; Unter .NET is das was anderes: Da is die Putzfrau schon bestellt um nach der virtuellen Party die verloren gegangenen Bits wieder zusammenzukehren... mfg Chriostian |
Re: Wann Destruktor-Aufruf nötig?
Zitat:
Mit der Methode Clear meinte ich die von das von dir angesprochene Reset, hab's nur Clear genannt, weil Hoika es in Beitrag #2 so genannt hatte. Ich kann aber ja schlecht Reset für ein Objekt aufrufen, welches bereits gelöscht wurde. Dieses Objekt müsste ich erst wieder neu erstellen. Deswegen wollte ich gleich alle Objekte neu erstellen. Haltet ihr es für geschickter, zu prüfen, welche Objekte noch bestehen und für diese Reset aufzurufen und nur die anderen zu createn? |
Re: Wann Destruktor-Aufruf nötig?
öhm ...
Also wenn Du ein Objekt aus der Liste löschst, solltest Du erst dessen .Free-Methode aufrufen und es dann tatsächlich aus der Liste entfernen. Diese hat danach eben ein Element weniger. Und wenn Du wieder auf 16 Elemente kommen möchtest, dann füllst Du eben auf. Aber auf diese Weise bist Du sicher, dass die Elemente, die noch in der Liste sind, definitiv auch benutzbar sind. Alles Andere wäre aus meiner Sicht softwaretechnische Kamikaze. Wie merkst Du Dir denn jetzt, auf welche Positionen Du noch zugreifen kannst und auf welche nicht? Oder vertraust Du auf das Glück des Anwenders? ;-) |
Re: Wann Destruktor-Aufruf nötig?
Zitat:
Hast du noch viele Objekte da, isses schneller diese zurückzusetzen, hast du wenige, isses schneller alle neu zu erstellen. In Anbetracht dessen, dass du nur ObjectList.Clear; aufrufen musst(OwnsObjects ist true) um alle Objete frei zu geben, und du das Erstellen aller objekte in ne separate Prozedur packen kannst, isses aber wohl deutlich einfacher alles neu zu erstellen... mfg Christian |
Re: Wann Destruktor-Aufruf nötig?
Zitat:
Delphi-Quellcode:
Faustregel 1:
Beispielprocedure TForm1.Button1Click(Sender: TObject);
var MyList : TStrings; begin 1. MyList := TStringlist.Create; // Hier wird das Objekt MyList erzeugt und belegt Arbeitsspeicher // In MyList wird eine Referenz (Zeiger) auf den reservierten // Arbeitsspeicher abgelegt. 2. MyList.Add('Test'); 3. MyList := TStringlist.Create; // Hier wird ebenfalls das Objekt MyList erzeugt und belegt Arbeitsspeicher // Was passiert aber mit dem unter 1. reservierten Arbeitsspeicher? // Gar nichts. Der Arbeitsspeicher wird durch das Create unter 3. weder // freigeben noch überschrieben. D.h. der Arbeitsspeicher bleibt reserviert und belegt // Da jetzt durch 3. MyList einen anderen Arbeitsspeicherblock referenziert ist der // Arbeitsspeicher von 1. für Dein Programm nicht mehr erreichbar und bleibt bis zum // Programmende belegt. 4. MyList.Add('Delphipraxis'); end;
Code:
Faustregel 2:
Was Du erzeugst musst Du auch wieder zerstören
Code:
Vor jedem erneuten Create die Methode Free aufrufen
|
Re: Wann Destruktor-Aufruf nötig?
Zitat:
Inzwischen denke ich mir aber, vielleicht geb ich den Objekten ne Boolean-Eigenschaft, unter der ich speicher, ob mit dem Objekt noch etwas gemacht werden soll. Dann behalte ich immer meine 16 Objekte und könnte auch später bequem die Reset-Methode aufrufen. Aber wie das mit dem Delete genau funzt, würde mich trotzdem interessieren. @ Jens Schumann: Danke, die Faustregeln werd ich mir merken :wink: |
Re: Wann Destruktor-Aufruf nötig?
Hallo Cöster,
wenn du innerhalb einer Schleife Elemente aus einer Liste (TList, TObjectList,...) entfernen möchtest, solltest du die Schleife rückwärts laufen lassen. Da beim Löschen die Listenlänge verändert wird, greifst du sonst bei den letzten Schleifendurchläufen auf nicht mehr gültige Elemente zu. Der Schleifenendwert wird vor dem Start der Schleife ermittelt und durch das Löschen nicht verändert. Gruß Hawkeye |
Re: Wann Destruktor-Aufruf nötig?
Zitat:
@ Hawkeye219: Ah, klingt logisch, das war auch der Fehler. Wundert mich nur, dass der Cursor beim Auftreten des Fehlers immer zu dem Aufruf einer anderen Methode gesprungen ist, in der der Fehler dann gar nicht aufgetreten ist. |
Re: Wann Destruktor-Aufruf nötig?
Zitat:
Zitat:
Gruß Hawkeye |
Re: Wann Destruktor-Aufruf nötig?
Zitat:
|
Re: Wann Destruktor-Aufruf nötig?
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:46 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz