
Martin Courteaux
Ist es erlaubt delete this;
wenn die delete-Anweisung die letzte Anweisung ist, die auf dieser Instanz der Klasse ausgeführt wird? Natürlich bin ich mir sicher, dass das Objekt durch die dargestellt wird this
-Zeiger ist new
ly-erstellt.
Ich denke an so etwas:
void SomeModule::doStuff()
{
// in the controller, "this" object of SomeModule is the "current module"
// now, if I want to switch over to a new Module, eg:
controller->setWorkingModule(new OtherModule());
// since the new "OtherModule" object will take the lead,
// I want to get rid of this "SomeModule" object:
delete this;
}
Kann ich das tun?

JaredPar
Die C++ FAQ Lite hat einen eigenen Eintrag dafür
Ich denke, dieses Zitat fasst es gut zusammen
Solange Sie vorsichtig sind, ist es in Ordnung, wenn ein Objekt Selbstmord begeht (löschen Sie dies).

Jerry Sarg
Jawohl, delete this;
hat definierte Ergebnisse, solange Sie (wie Sie bemerkt haben) sicherstellen, dass das Objekt dynamisch zugewiesen wurde, und (natürlich) niemals versuchen, das Objekt zu verwenden, nachdem es zerstört wurde. Im Laufe der Jahre wurden viele Fragen dazu gestellt, was die Norm konkret aussagt delete this;
, im Gegensatz zum Löschen eines anderen Zeigers. Die Antwort darauf ist ziemlich kurz und einfach: Sie sagt nicht viel aus. Das sagt es einfach delete
Der Operand von muss ein Ausdruck sein, der einen Zeiger auf ein Objekt oder ein Array von Objekten bezeichnet. Es geht ziemlich detailliert auf Dinge ein, wie es herausfindet, welche (wenn überhaupt) Freigabefunktion aufgerufen werden muss, um den Speicher freizugeben, aber den gesamten Abschnitt weiter delete
(§[expr.delete]) nicht erwähnt delete this;
konkret überhaupt. Der Abschnitt über Destruktor erwähnt delete this
in einem Platz (§[class.dtor]/13):
Am Definitionspunkt eines virtuellen Destruktors (einschließlich einer impliziten Definition (15.8)) wird die Nicht-Array-Freigabefunktion bestimmt, als ob für den Ausdruck delete this in einem nicht virtuellen Destruktor der Klasse des Destruktors erscheint (siehe 8.3.5 ).
Dies unterstützt tendenziell die Idee, die der Standard berücksichtigt delete this;
um gültig zu sein – wenn es ungültig wäre, wäre sein Typ nicht aussagekräftig. Das ist die einzige Stelle, die der Standard erwähnt delete this;
überhaupt, soweit ich weiß.
Wie auch immer, einige denken darüber nach delete this
ein fieser Hack, und sagen Sie jedem, der zuhört, dass er vermieden werden sollte. Ein häufig genanntes Problem ist die Schwierigkeit sicherzustellen, dass Objekte der Klasse immer nur dynamisch zugewiesen werden. Andere halten es für eine vollkommen vernünftige Redewendung und verwenden es ständig. Ich persönlich liege irgendwo in der Mitte: Ich benutze es selten, aber zögere nicht, es zu tun, wenn es das richtige Werkzeug für den Job zu sein scheint.
Am häufigsten verwenden Sie diese Technik bei einem Objekt, das ein fast völlig eigenes Leben hat. Ein Beispiel, das James Kanze genannt hat, war ein Abrechnungs-/Verfolgungssystem, an dem er für eine Telefongesellschaft gearbeitet hat. Wenn Sie anfangen zu telefonieren, nimmt etwas davon Notiz und erstellt einen phone_call
Objekt. Ab diesem Zeitpunkt ist die phone_call
Das Objekt verarbeitet die Details des Telefonanrufs (Herstellen einer Verbindung beim Wählen, Hinzufügen eines Eintrags zur Datenbank, der angibt, wann der Anruf begonnen hat, möglicherweise mehr Personen verbinden, wenn Sie eine Telefonkonferenz durchführen usw.) Wann die letzten Personen im Anruf sind auflegen, die phone_call
Das Objekt führt seine endgültige Buchführung durch (z. B. fügt einen Eintrag zur Datenbank hinzu, der angibt, wann Sie aufgelegt haben, damit sie berechnen können, wie lange Ihr Anruf gedauert hat) und zerstört sich dann selbst. Die Lebensdauer der phone_call
Objekt basiert darauf, wann die erste Person den Anruf startet und wann die letzten Personen den Anruf verlassen – aus der Sicht des restlichen Systems ist es im Grunde völlig willkürlich, also Sie kippen binden Sie es an einen beliebigen lexikalischen Bereich im Code oder irgendetwas in dieser Reihenfolge.
Für alle, die sich dafür interessieren, wie zuverlässig diese Art der Verschlüsselung sein kann: Wenn Sie in, aus oder durch fast alle Teile Europas telefonieren, besteht eine ziemlich gute Chance, dass dies (zumindest teilweise) per Code abgewickelt wird das macht genau das.

Mark Lösegeld
Wenn es dir Angst macht, gibt es einen vollkommen legalen Hack:
void myclass::delete_me()
{
std::unique_ptr<myclass> bye_bye(this);
}
Ich denke delete this
ist jedoch idiomatisches C++, und ich präsentiere dies nur als Kuriosität.
Es gibt einen Fall, in dem dieses Konstrukt tatsächlich nützlich ist – Sie können das Objekt löschen, nachdem Sie eine Ausnahme ausgelöst haben, die Mitgliedsdaten aus dem Objekt benötigt. Das Objekt bleibt gültig, bis der Wurf erfolgt ist.
void myclass::throw_error()
{
std::unique_ptr<myclass> bye_bye(this);
throw std::runtime_exception(this->error_msg);
}
Hinweis: Wenn Sie einen Compiler verwenden, der älter als C++11 ist, können Sie verwenden std::auto_ptr
anstatt std::unique_ptr
es wird dasselbe tun.

Bob Bryan
Einer der Gründe, warum C++ entwickelt wurde, war die einfache Wiederverwendung von Code. Im Allgemeinen sollte C++ so geschrieben werden, dass es funktioniert, egal ob die Klasse auf dem Heap, in einem Array oder auf dem Stack instanziiert wird. “Delete this” ist eine sehr schlechte Codierungspraxis, da es nur funktioniert, wenn eine einzelne Instanz auf dem Heap definiert ist; und es sollte besser keine weitere delete-Anweisung geben, die normalerweise von den meisten Entwicklern verwendet wird, um den Heap aufzuräumen. Dies setzt auch voraus, dass kein Wartungsprogrammierer in der Zukunft ein fälschlicherweise wahrgenommenes Speicherleck beheben wird, indem er eine Löschanweisung hinzufügt.
Selbst wenn Sie im Voraus wissen, dass Ihr derzeitiger Plan darin besteht, nur eine einzige Instanz auf dem Heap zuzuweisen, was ist, wenn in Zukunft ein fröhlicher Entwickler vorbeikommt und beschließt, eine Instanz auf dem Stapel zu erstellen? Oder was ist, wenn er bestimmte Teile der Klasse ausschneidet und in eine neue Klasse einfügt, die er auf dem Stapel verwenden möchte? Wenn der Code “delete this” erreicht, wird er losgehen und ihn löschen, aber wenn das Objekt dann den Gültigkeitsbereich verlässt, ruft er den Destruktor auf. Der Destruktor wird dann versuchen, es erneut zu löschen, und dann werden Sie abgespritzt. In der Vergangenheit hätte so etwas nicht nur das Programm vermasselt, sondern auch das Betriebssystem und der Computer müsste neu gestartet werden. In jedem Fall wird dies dringend NICHT empfohlen und sollte fast immer vermieden werden. Ich müsste verzweifelt, ernsthaft verputzt sein oder die Firma, für die ich gearbeitet habe, wirklich hassen, um Code zu schreiben, der dies tut.
Es ist erlaubt (verwenden Sie das Objekt danach einfach nicht), aber ich würde solchen Code nicht zum Üben schreiben. ich denke, dass delete this
sollte nur in aufgerufenen Funktionen erscheinen release
oder Release
und sieht aus wie: void release() { ref--; if (ref<1) delete this; }
.

UnbekanntGosu
Nun, im Komponentenobjektmodell (COM) delete this
Konstruktion kann ein Teil davon sein Release
Methode, die aufgerufen wird, wenn Sie ein erworbenes Objekt freigeben möchten:
void IMyInterface::Release()
{
--instanceCount;
if(instanceCount == 0)
delete this;
}

Zack Yezek
Dies ist die Kernsprache für referenzgezählte Objekte.
Das Zählen von Referenzen ist eine starke Form der deterministischen Garbage Collection – es stellt sicher, dass Objekte ihre EIGENE Lebensdauer verwalten, anstatt sich auf “intelligente” Zeiger usw. zu verlassen, um dies für sie zu tun. Auf das zugrunde liegende Objekt wird immer nur über intelligente “Referenz”-Zeiger zugegriffen, die so ausgelegt sind, dass die Zeiger eine Element-Ganzzahl (die Referenzzählung) im tatsächlichen Objekt erhöhen und verringern.
Wenn die letzte Referenz aus dem Stapel fällt oder gelöscht wird, geht der Referenzzähler auf Null zurück. Das Standardverhalten Ihres Objekts ist dann ein Aufruf von „delete this“ an die Garbage Collection – die Bibliotheken, die ich schreibe, stellen einen geschützten virtuellen „CountIsZero“-Aufruf in der Basisklasse bereit, sodass Sie dieses Verhalten für Dinge wie das Caching außer Kraft setzen können.
Der Schlüssel, um dies sicher zu machen, besteht darin, Benutzern keinen Zugriff auf den CONSTRUCTOR des betreffenden Objekts zu gewähren (es geschützt zu machen), sondern sie stattdessen dazu zu bringen, ein statisches Mitglied – die FACTORY – wie “statische Referenz CreateT (…)” aufzurufen. Auf diese Weise WISSEN Sie sicher, dass sie immer mit gewöhnlichen “neuen” erstellt werden und dass kein roher Zeiger jemals verfügbar ist, sodass “delete this” niemals explodiert.
9956400cookie-checkIst “delete this” in C++ erlaubt?yes
Hauptproblem wäre, wenn Sie
delete this
Sie haben eine enge Kopplung zwischen der Klasse und der Zuordnungsmethode erstellt, die zum Erstellen von Objekten dieser Klasse verwendet wird. Das ist sehr schlechtes OO-Design, da die grundlegendste Sache in OOP darin besteht, autonome Klassen zu erstellen, die nicht wissen oder sich nicht darum kümmern, was ihr Aufrufer tut. Daher sollte eine richtig entworfene Klasse nicht wissen oder sich darum kümmern, wie sie zugewiesen wurde. Wenn Sie aus irgendeinem Grund einen solchen besonderen Mechanismus benötigen, wäre es meiner Meinung nach besser, eine Wrapper-Klasse um die eigentliche Klasse herum zu verwenden und den Wrapper die Zuweisung erledigen zu lassen.– Ludin
14. Oktober 2015 um 7:58 Uhr
Kannst du nicht löschen
setWorkingModule
?– Jimmy T.
12. April 2020 um 10:35 Uhr
@Lundin CFrameWnd Klasse von MFC tut
delete this;
inPostNcDestroy
denn dann wird die WinAPI-Klasse, die sie umschließt, vermutlich zerstört. Es hat also seine eigenen gültigen Anwendungsfälle, würde ich sagen.– Ayxan Haqverdili
29. November 2020 um 18:42 Uhr
@Lundin Das Problem ist nicht die Freigabe, sondern die Zerstörung. In C++ besteht die einzig richtige Möglichkeit, diese beiden zu trennen und dennoch Kapselung und Polymorphismus zu erreichen, darin, shared_ptr zu verwenden. Unique_ptr trennt sie nicht. Die betreffende Klasse kümmert sich nicht um die Zuweisung/Aufhebung der Zuweisung, aber sie möchte ihre Lebensdauer kontrollieren. Ich würde wetten, dass die fragliche Klasse mit shared_ptr/enable_shared_from_this richtig entworfen werden kann, aber ich mag es nicht, dass es so gemacht werden muss, zumal shared_ptr/enable_shared_from_this viel Codegröße verbrauchen und daher für meine eingebettete Entwicklung unbrauchbar sind .
– Dragan
16. Juli 2021 um 10:49 Uhr