17 Stimmen

Ist "dies löschen" eine schlechte Idee?

Mögliches Duplikat:
Ist es sicher, dass delete this ?

Ich habe ein wenig an einer Klasse gearbeitet, die als Knoten in einer verknüpften Liste fungieren soll, und ich dachte mir, ich gebe der Klasse ihre eigene Löschfunktion, anstatt dass die Verwaltungsklasse das tut. Also im Grunde geht es wie folgt:

void Class::Delete() {
    //Some cleanup code before deleting the object
    delete this;
}

Ich habe dies nun getestet und es scheint gut zu funktionieren, aber ich hatte in der Vergangenheit ein Problem, bei dem Objekte mitten im laufenden Code waren, gelöscht wurden und dann offensichtlich das Programm abstürzte, weil es versuchte, ein nicht mehr vorhandenes Objekt zu verwenden.

Da "delete this" ganz am Ende der Funktion steht, wird die Funktion natürlich beendet und funktioniert einwandfrei, aber ist diese Art von Praxis überhaupt eine schlechte Idee? Könnte mir das jemals zum Verhängnis werden, wenn ich nicht vorsichtig bin?

22voto

Dominic Gurto Punkte 3785

En FAQlite beantwortet diese Frage recht gut:

Solange Sie vorsichtig sind, ist es in Ordnung für ein Objekt Selbstmord begehen kann (löschen dies).

Ich definiere "vorsichtig" folgendermaßen:

  1. Sie müssen absolut 100%ig sicher sein, dass dieses Objekt über new zugewiesen wurde (nicht über new[], noch durch placement new, noch durch ein lokales Objekt auf dem Stack, noch ein globales, noch ein Mitglied eines anderen Objekts; sondern durch einfaches gewöhnliches new).
  2. Sie müssen absolut 100%ig sicher sein, dass Ihr Mitglied Funktion die letzte Memberfunktion sein wird Funktion ist, die für dieses Objekt aufgerufen wird.
  3. Sie müssen sich absolut 100%ig sicher sein, dass die r Mitgliedsfunktion (nach der Zeile delete this Zeile) keinen Teil dieser Funktion berührt Objekts berührt (einschließlich des Aufrufs einer anderen Mitgliedsfunktionen oder irgendwelche Daten Mitglieder).
  4. Sie müssen absolut 100%ig sicher sein, dass den Zeiger selbst nach der diese Zeile löschen. Mit anderen Worten, Sie dürfen ihn nicht untersuchen, ihn mit einem anderen Zeiger vergleichen, ihn mit NULL vergleichen, drucken, casten, irgendetwas mit ihm machen tun.

Natürlich sind die üblichen c Fällen, in denen Ihr dieser Zeiger ein Zeiger auf eine Basisklasse ist, wenn Sie keine einen virtuellen Destruktor haben.

Im Grunde müssen Sie die gleiche Sorgfalt walten lassen wie bei delete einem beliebigen anderen Zeiger. Es gibt jedoch mehr Bereiche, in denen Dinge schief gehen können, wenn eine Mitgliedsfunktion Selbstmord begeht, verglichen mit einem explizit deklarierten Zeiger.

6voto

Alok Save Punkte 196241

Verwendung von delete this ist eine schlechte Idee, wenn man sich der Fallstricke nicht sicher ist und sie umgehen kann.

Sobald Sie anrufen delete this wird der Destruktor des Objekts aufgerufen und der dynamisch zugewiesene Speicher wird freigegeben.

Wurde das Objekt nicht mit new wird es ein Undefined behaviour .
Wenn auf Datenelemente oder virtuelle Funktionen des Objekts zugegriffen wird, nachdem delete this wird das Verhalten Undefined Behavior wieder.

Wahrscheinlich ist es am besten zu vermeiden delete this in Anbetracht der obigen Ausführungen.

4voto

James Kanze Punkte 146902

Es ist eine häufige Redewendung und so sicher wie jedes Löschen. Wie müssen Sie sicherstellen, dass kein weiterer Code versucht, auf das Objekt auf das Objekt zuzugreifen, und Sie müssen sicher sein, dass das Objekt dynamisch zugewiesen wurde. Normalerweise ist letzteres jedoch kein kein Problem, da das Idiom nur für Objekte relevant ist, deren Lebensdauer haben, die durch die Semantik des Objekts bestimmt wird, und solche Objekte werden immer dynamisch zugewiesen werden. Die Suche nach allen Zeigern auf das Objekts kann ein Problem sein (ob delete this verwendet wird oder nicht); normalerweise, wird eine Form des Beobachtermusters verwendet, um alle interessierten Parteien zu informieren, dass das Objekt aufhört zu existieren.

2voto

GogaRieger Punkte 345

Die idiomatische Art und Weise, dies in C++ zu tun, besteht darin, den Aufräumcode in den Destruktor zu stellen und ihn dann automatisch aufrufen zu lassen, wenn Sie das Objekt löschen.

Class::~Class() {
    do_cleanup();
}

void ManagingClass::deleteNode(Class* instance) {
    delete instance; //here the destructor gets called and memory gets freed
}

1voto

Mark Ransom Punkte 283960

Es gibt eine einfache Möglichkeit, das Gleiche zu tun, ohne dass ein undefiniertes Verhalten vorliegt:

void Class::Delete() {
    //Some cleanup code before deleting the object
    std::auto_ptr delete_me(this);
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X