Ist es in Ordnung, "delete this" zu verwenden, um das aktuelle Objekt zu löschen?

7

Ich schreibe eine verkettete Liste und möchte, dass der Destruktor einer Struktur (eine Node-Struktur) sich selbst löscht und keine Nebenwirkungen hat. Ich möchte, dass der Destruktor meiner Liste iterativ den Node-Destruktor für sich selbst aufruft (den nächsten Knoten vorübergehend speichert), wie folgt:

%Vor%

Das wäre also mein Node-Destruktor:

%Vor%

Ist das akzeptabel, besonders in diesem Zusammenhang?

    
jkeys 11.08.2009, 01:26
quelle

8 Antworten

17

Wenn der Node-Destruktor aufgerufen wird, wird er gerade gelöscht. Daher macht ein Löschen in Ihrem Node-Destruktor keinen Sinn.

Auch das ist falsch:

%Vor%

Stattdessen sollten Sie temp- & gt; next () in eine temporäre Variable aufnehmen. Andernfalls greifen Sie auf gelöschten Speicher zu.

Also eher so:

%Vor%     
Brian R. Bondy 11.08.2009 01:34
quelle
4

Nein, du solltest nicht delete this vom Destruktor haben. Der Destruktor wird wegen einer Löschanweisung aufgerufen (oder geht aus dem Geltungsbereich) und dies würde höchstwahrscheinlich zu einer Art Absturz führen.

Sie haben auch ein paar Probleme im DoublyLinkedList-Destraktor. One, Sie löschen Temp und dann Temp, nachdem es gelöscht wurde. Zweitens löscht der Code das letzte Element in der verknüpften Liste nicht wirklich.

    
Brian Ensink 11.08.2009 01:37
quelle
4

Gegenwärtig würde Ihr Code eine Zugriffsverletzung verursachen, da die zweite der folgenden Zeilen eindeutig auf freigegebenen Speicher zugreift:

%Vor%

Wenn Sie die Struktur rekursiv löschen möchten, möchten Sie etwa Folgendes:

%Vor%     
Dmitry Brant 11.08.2009 01:40
quelle
1

lösche dies; würde den Destruktor des aktuellen Objekts aufrufen. In diesem Fall, wenn Sie anrufen, löschen Sie dies; im Destruktor würde der Destruktor unendlich bis zum Absturz aufgerufen werden.

    
Jagannath 11.08.2009 01:37
quelle
1

Vor allem anderen: Ich hoffe wirklich, dass es sich hier um Hausaufgaben handelt, um eine doppelt verknüpfte Liste zu verstehen. Ansonsten gibt es keinen Grund, dies anstelle von std::list zu verwenden. Damit nicht im Weg:

Nein, delete this in einem dtor ist immer falsch, da der dtor aufgerufen wird, wenn this im Status gelöscht wird.

Auch während

%Vor%

könnte übrigens funktionieren, es ist sicherlich falsch, da, wo Sie versuchen, auf temp->next() zuzugreifen, temp bereits gelöscht ist, also sollten Sie eine Member-Funktion darauf aufrufen. Dies führt zu einem sogenannten "undefinierten Verhalten". (Kurz gesagt: Es könnte tun, was Sie wollen, aber es könnte genauso gut immer oder sporadisch versagen oder nur, wenn Freitag, 13., mit Neumond kollidiert. Es könnte auch böse Dämonen auf Sie heraufbeschwören .)

Beachten Sie, dass Sie beide Probleme lösen könnten, indem Sie den nächsten Knoten im Knoten dtor:

löschen %Vor%

Auf diese Weise wird Ihre Liste dtor auch sehr einfach:

%Vor%

Für mich scheint das, wofür dtors erfunden wurden, also abgesehen davon, dass heute niemand mehr eigene Linkedlist-Typen schreiben sollte, für mich scheint das die C ++ Lösung zu sein Problem.

    
sbi 11.08.2009 08:57
quelle
0

Der obige Code ruft Node :: ~ Node () zweimal auf. (in "delete temp" und in Node :: ~ Node ())

Node :: ~ Node () sollte nicht "delete this" aufrufen (oder Ihr Programm wird abstürzen)

ps. While-Schleife in Ihrem Code wird nicht funktionieren. Es wird ungültiger Zeiger dereferenziert. Sie sollten zuerst den Wert von temp- & gt; als nächstes kopieren und dann den temporären Zeiger löschen.

    
rein 11.08.2009 01:37
quelle
0

Im Allgemeinen sollte sich ein Destruktor nur um das Löschen (oder Freigeben von C oder malloc) kümmern, wenn der Speicher speziell für Ihr Objekt reserviert ist. Löschen eines Zeigers auf Ihr Objekt wird immer vom Betriebssystem verwaltet und Sie müssen sich keine Gedanken über diesen Teil machen.

Beachten Sie, dass Sie bei der Konstruktion zuerst das Objekt erstellen (da der Kontrollfluss in den Körper des Konstruktors eintritt), DANN die Objekte im Inneren; Für die Zerstörung müssen Sie das umgekehrt tun, denn wenn Sie das äußere Objekt zuerst löschen, haben Sie keine Möglichkeit, auf die inneren Zeiger zuzugreifen, um diese zu löschen. Stattdessen löschen Sie innere Objekte mithilfe des Destruktors, und das Betriebssystem verwaltet dann die tatsächliche Speicherfreigabe, wenn der Steuerungsfluss aus dem Destruktor herausfällt.

Übrigens, die gleiche Art von Sache passiert mit Unterklassen - wenn Sie Klasse A und Klasse B haben: public A, dann, wenn Sie eine neue B (), führt der A-Konstruktor zuerst, dann der B-Konstruktor; Bei der Destruktion wird der Destruktor von B zuerst ausgeführt, gefolgt von A. Ich bin ziemlich sicher, dass Sie sich darüber nicht sorgen müssen, obwohl - C ++ kümmert sich darum für Sie. Versuchen Sie also nicht, einen Weg zum Aufrufen von delete in der Oberklasse zu finden.

    
Platinum Azure 11.08.2009 01:44
quelle
0

Beide sollten nie gemacht werden.

Dies

%Vor%

führt zu undefiniertem Verhalten - Sie dürfen nicht auf den Speicher zugreifen, den Sie an den Heap zurückgegeben haben. Stattdessen sollte es sein:

%Vor%

Der Aufruf von delete this führt zu sogenanntem double free, was ebenfalls zu undefiniertem Verhalten führt. Der Destruktor sollte nur für Zeigerelementvariablen löschen, niemals für this . Der Aufruf von delete this ist für andere Methoden sinnvoll, um das aktuelle Objekt, aber nicht vom Destruktor zu entfernen.

    
sharptooth 11.08.2009 09:05
quelle