Destruktor wird zu früh ausgeführt!
-
Hallo!
Ich habe eine Klasse mit einem "new int[xyz]"-Array, dazugehörigem Zeiger und einigen Integer-Variablen. Anfang einer Funktion wird ein Objekt dieser Klasse erstellt. Am Ende wird genau dieses Objekt mit "return" zurückgegeben.
Das Problem ist das mein Destruktor am Ende des blocks mit "delete[]" das Array innerhalb der Klasse löscht und der zurückgegebene Wert Müll ist!
Wenn ich den Dafault-Destruktor verwende werden die Arrays garnicht vernichtet.
Das führt leider zu bis zu 800mb Arbeitspeicherverbrauch durch die zahlreichen Array-Leichen! (bei einem Gb RAM...)Mit dem Dafault-Destruktor werden komischerweise die richtigen Werte zurückgegeben, obwohl ausser dem Array, doch alle anderen Variablen (inklusive des Zeigers auf das Array) des Objektes gelöcht werden müssten.
Bitte erklärt mir, wieso der Dafault-Destruktor richtige Werte ausspuckt und wie ich ohne Speicherleichen richtige Werte erhalte!
Danke im voraus.
NevaPS: Warum wird "v"o"r"r"a"u"s" (mit 2r, was ja falsch ist) hier im Forum mit "*" verdeckt???
-
Wenn du die Klasse by value zurückgibst, wird am Ende der Funktion eine Kopie angelegt. Das Originalobjekt wird zerstört. Das Problem ist hier nicht der Destruktor, sondern der compilergenerierte Copykonstruktor, denn der kopiert nur den Zeiger-Member selbst.
Es gibt eine Regel, die besagt: Wenn deine Klasse einen der drei Destruktor/Copy-Ctor/Zuweisungsoperator braucht, dann braucht sie alle drei.
-
Das Problem ist das mein Destruktor am Ende des blocks mit "delete[]" das Array innerhalb der Klasse löscht und der zurückgegebene Wert Müll ist!
richtiges verhalten. Beim rausgehen aus dem block werden all seine lokalen variablen gekillt, dh der dtor wird aufgerufen. der grund, weshalb der default dtor deinen mit new erstellten speicher nicht löscht ist, dass er garnicht weis, dass du mit new[] speicher allokierst, oder ob du den speicher noch brauchst, um sowas musst du dich kümmern.
einfachste lösung: benutze vectoren, dann brauchste dich garnicht mehr um sowas zu kümmern
andere lösungen:
- versuche referenzen zurückzugeben
- implementier einen copy ctor, der das ganze array neu allokiert und kopiert(anstatt einfach nur den zeiger zu kopieren, was default behaviour ist).
-benutz boost::shared_ptr(kommt auf die situation an)
-
Neva schrieb:
PS: Warum wird "v"o"r"r"a"u"s" (mit 2r, was ja falsch ist) hier im Forum mit "*" verdeckt???
Weil der Anblick auf Dauer nervt
-
Danke für die schnelle Antwort!
Das mit dem copy-Konstruktor werde ich gleich machen. Da stand ich wohl auf dem Schlauch...
Da meine Arrays aber recht groß sind und der beschriebne Fall sehr oft auftritt, könnte das mein Programm leider ziemlich bremsen.Wenn ich Referenzen zurückgeben will muss ich das Objekt schon außerhalb des Blocks erstellen und dann auch eine Referenz davon einfügen. Oder war was anderes gemeint?
Und für die eventuelle Lösung mit "boost::shared_ptr" besteht bei mir noch etwas Erklärungsbedarf. Wäre sehr nett wenn jemand kurz Zeit hätte mir das zu erklären.
Neva
-
Eigentlich bräuchtest du bei deinem Zweck nur den Zeiger weiterzureichen und der Empfänger löscht den Speicher dann später oder reicht ihn selber weiter und für sowas sind smart pointer ideal
-
Was ist ein "smart pointer" und wie benutzt man ihn?
Neva
-
Ich hoffe der Link reicht dir aus sonst musst du selber etwas suchen.
http://www.codeproject.com/vcpp/stl/boostsmartptr.aspNen Smart Pointer ist eine Klasse welche sich wie ein Zeiger verhält, ersetzt zwar nicht zu 100% einen Zeiger, aber man kann sich mit ihnen viel Arbeit und viele Fehler ersparen.