Ist löschen erlaubt?
Ist es erlaubt delete this;
wenn der delete-Anweisung ist die Letzte Anweisung, die ausgeführt werden, auf diese Instanz der Klasse? Natürlich bin ich sicher, dass das Objekt, vertreten durch die this
-Zeiger ist new
ly erstellt.
Ich denke über so etwas wie dieses:
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 tun?
Hauptproblem würde sein, dass, wenn Sie
delete this
Sie haben eine enge Kopplung zwischen der Klasse und die Mittelzuweisung Methode für die Erstellung von Objekten der Klasse. Das ist sehr schlechtes OO-design, da die meisten grundlegende Sache bei der OOP ist die autonome Klassen, die nicht wissen oder kümmern uns um das, was Ihre Anrufer zu tun. Also ein richtig Klasse sollte nicht wissen, oder kümmern uns um, wie es zugeteilt wurde. Wenn Sie aus irgendeinem Grund brauchen einen eigenartigen Mechanismus, denke ich, ein besseres design würde die Verwendung einer wrapper-Klasse um die eigentliche Klasse, und lassen Sie die wrapper befassen sich mit der Aufteilung.InformationsquelleAutor Martijn Courteaux | 2010-06-30
Du musst angemeldet sein, um einen Kommentar abzugeben.
Der C++ FAQ Lite hat einen Eintrag, der speziell für diese
Ich denke, das Zitat fasst es gut
Zur Sicherheit können Sie die Verwendung privater Destruktor auf das ursprüngliche Objekt zu stellen Sie sicher sein, nicht konstruiert, die auf dem stack oder als Teil des array-oder vector.
Definieren Sie 'vorsichtig'
'Aufpassen' ist definiert in der verlinkten FAQ Artikel. (Während der FQA link meist erfreuliches - wie fast alles in der it - wie schlecht C++ ist)
InformationsquelleAutor JaredPar
Ja,
delete this;
hat definierte Ergebnisse, solange (wie du schon angemerkt) sichern Sie das Objekt wurde dynamisch zugewiesen, und es (natürlich) nie versuchen, das Objekt zu verwenden, nachdem es zerstört. Im Laufe der Jahre viele Fragen gestellt zu haben, über das, was der standard sagt, speziell überdelete this;
im Gegensatz zu löschen einige andere Zeiger. Die Antwort auf diese Frage ist ziemlich kurz und einfach: es bedeutet nicht, viel von etwas sagen. Es sagt nur, dassdelete
's operand muss ein Ausdruck sein, der bezeichnet, einen Zeiger auf ein Objekt, oder ein array von Objekten. Es geht in ein bisschen ausführlich über Dinge wie, wie er berechnet, was (wenn vorhanden) - Freigabe-Funktion aufrufen, um den Speicher freizugeben, aber der gesamte Abschnitt aufdelete
(§[expr.löschen]) nicht erwähntdelete this;
sich speziell an alle. Der Abschnitt über destrucors erwähntdelete this
an einer Stelle (§[Klasse.dtor]/13):Die tendenziell unterstützen die Idee, dass die standard-Ansicht
delete this;
gültig zu sein--wenn es ungültig war, seine Art wäre nicht sinnvoll. Das ist der einzige Ort, der standard nenntdelete this;
an alle, soweit ich weiß.Trotzdem halten einige
delete this
einen fiesen hack, und niemandem sagen, wer hört, dass es vermieden werden sollte. Ein Häufig genanntes problem ist die Schwierigkeit, sicherzustellen, dass Objekte der Klasse sind immer nur dynamisch zugewiesen. Andere halten es für eine durchaus vernünftige idiom, und verwenden Sie es die ganze Zeit. Ich persönlich bin irgendwo in der Mitte: ich habe selten verwenden, aber zögern Sie nicht, um so zu tun, als es zu sein scheint, das richtige Werkzeug für den job.Die primäre Zeit, die Sie verwenden, diese Technik ist mit einem Objekt, einem Leben, das fast ausschließlich seine eigenen. Ein Beispiel James Kanze hat, zitiert wurde ein billing/tracking-system, arbeitete er für eine Telefongesellschaft. Wenn starten Sie einen Anruf tätigen, etwas zur Kenntnis nimmt, und schafft eine
phone_call
Objekt. Von diesem Punkt an, diephone_call
- Objekt verarbeitet die Einzelheiten der Anruf (eine Verbindung, wenn Sie wählen, fügen Sie einen Eintrag in die Datenbank zu sagen, wenn der Anruf gestartet wurde, möglicherweise schließen Sie mehr Menschen, wenn Sie eine Telefonkonferenz, etc.) Wenn die letzten Menschen auf den Anruf auflegen, diephone_call
Objekt hat seine letzten Buch-zu halten (z.B., fügt einen Eintrag in die Datenbank zu sagen, wenn Sie aufgehängt werden, so können Sie berechnen, wie lange Ihr Anruf wurde) und dann sich selbst zerstört. Die Lebensdauer derphone_call
Objekt ist, basierend auf, wenn die erste person beginnt die anrufen und wenn die letzten Menschen verlassen das call--aus der Sicht von dem rest des Systems, es ist im Grunde völlig willkürlich ist, so dass Sie nicht binden Sie es zu jeder lexikalischen Bereich im code, oder etwas an dieser Reihenfolge.Für alle, die vielleicht interessieren, wie verlässlich diese Art der Codierung werden kann: wenn Sie einen Telefonanruf tätigen, um, aus, oder durch fast jedem Teil von Europa, es ist eine ziemlich gute chance, dass es behandelt wird, (zumindest teilweise) durch code, der tut genau dies.
Würden Sie vermutlich, dass in den meisten Fällen jedenfalls-ich weiß nicht, irgendwo in der Nähe zu allen details des Systems, er war arbeiten, also kann ich nicht sagen, für sicher, obwohl.
Die Art und Weise, die ich oft bekommen, um das problem, wie der Speicher reserviert wurde unter anderem ein
bool selfDelete
parameter im Konstruktor zugewiesen bekommt, um eine member-variable. Zugegeben, dies bedeutet, dass die übergabe der Programmierer genügend Seil zum binden einer Schlinge, aber ich finde, dass vorzuziehen, um memory-leaks.Ich habe das gleiche getan, aber lieber zu vermeiden, was scheint mir, wie eine Behelfslösung.
Für alle, die vielleicht Sorge ... es ist eine ziemlich gute chance, dass es behandelt wird, (zumindest teilweise) durch code, der genau das tut
this
. Ja, der code behandelt werden, die genauthis
. 😉InformationsquelleAutor Jerry Coffin
Wenn es Sie erschreckt, es ist ein ganz legaler hack:
Ich denke
delete this
ist die idiomatischen C++ - obwohl, und ich nur diese als Neugier.Es ist ein Fall, wo dieses Konstrukt ist tatsächlich nützlich - Sie können löschen Sie das Objekt nach dem auslösen einer Ausnahme muss Mitglied Daten aus dem Objekt. Das Objekt bleibt solange gültig, bis nach dem werfen findet.
Hinweis: wenn Sie mit einem compiler, die älter als C++11 können Sie
std::auto_ptr
stattstd::unique_ptr
es wird das gleiche tun.Ich kann nicht ankommen dieses zu kompilieren mit c++11, gibt es einige spezielle compiler-Optionen für Sie? Auch ist es nicht erforderlich, ein bewegen der this-Zeiger?
nicht sicher, was du meinst, es funktioniert bei mir: ideone.com/aavQUK. Erstellen einer
unique_ptr
von andereunique_ptr
erfordert eine Bewegung, aber nicht aus einem raw-pointer. Wenn sich die Dinge geändert in C++17?Ahh C++14, das wird der Grund sein. Ich aktualisieren mein c++ auf meiner dev-box. Ich werde versuchen heute Abend wieder auf meinem vor kurzem gentoo system!
InformationsquelleAutor Mark Ransom
Einer der Gründe, warum C++ wurde entworfen war, um es einfach, um code wiederzuverwenden. Im Allgemeinen, C++, geschrieben werden sollte, so dass es funktioniert unabhängig davon, ob die Klasse instanziiert wird, wird auf dem heap in einem array oder auf dem stack. "Löschen" ist ein sehr schlechter Programmierstil, weil es nur funktioniert, wenn eine einzelne Instanz definiert ist, über den Haufen; und es wäre besser, nicht zu einem weiteren delete-Anweisung, die in der Regel von den meisten Entwicklern zu reinigen heap. Dadurch wird auch davon ausgegangen, dass keine Wartung-Programmierer in der Zukunft heilen wird, eine falsch wahrgenommene Speicherverlust durch hinzufügen einer delete-Anweisung.
Selbst wenn Sie im Voraus wissen, dass Ihre aktuelle plan ist, nur weisen Sie eine einzelne Instanz auf dem heap, was ist, wenn einige happy-go-lucky-Entwickler kommt in die Zukunft und entscheidet, erstellen Sie eine Instanz auf dem stack? Oder was wäre, wenn er schneidet und Pasten bestimmte Teile der Klasse in eine neue Klasse, die er zu verwenden beabsichtigt, auf dem Stapel? Wenn der code erreicht "löschen" es wird gehen und es löschen, aber dann, wenn das Objekt den Gültigkeitsbereich verlässt, es ruft den Destruktor. Der Destruktor wird dann versuchen, wieder löschen und dann sind Sie abgespritzt. In der Vergangenheit, etwas wie das zu tun wäre, Schraube, bis nicht nur das Programm, sondern das Betriebssystem und der computer muss neu gestartet werden. In jedem Fall ist es in hohem Grade NICHT empfohlen und sollten fast immer vermieden werden. Hätte ich zu verzweifelt, ernst verputzt, oder hasse die Firma, für die ich arbeitete, um code zu schreiben, Tat dies.
Joh - danke für die upvote! Ich verstehe nicht, entweder...
Sie konnte nur wickeln Sie das Objekt, das Sie löschen möchten, die sich in eine spezielle Klasse, die löscht das Objekt und dann sich selbst, und verwenden Sie diese Technik zur Vermeidung von stack-Allokation: stackoverflow.com/questions/124880/... Es gibt Zeiten, wenn es wirklich keine brauchbare alternative. Ich habe gerade verwendet diese Technik, um sich selbst löschen, ein thread, der gestartet wird, indem Sie eine DLL-Funktion, sondern die Funktion in der DLL müssen zurück, bevor der thread endet.
InformationsquelleAutor Bob Bryan
Es erlaubt ist (weiß nur nicht dem Objekt nach, dass), aber ich würde nicht schreiben, wie der code auf die Praxis. Ich denke, dass
delete this
erscheinen soll, nur in Funktionen, die aufgerufenrelease
oderRelease
und sieht wie folgt aus:void release() { ref--; if (ref<1) delete this; }
.InformationsquelleAutor Kirill V. Lyadvinsky
Gut, Component Object Modell (COM)
delete this
Konstruktion kann ein Teil derRelease
Methode, die aufgerufen wird, wenn Sie Sie freigeben möchten aquisited Objekt:InformationsquelleAutor UnknownGosu
Können Sie dies tun. Sie können jedoch nicht zuordnen. Also der Grund warum Sie dies zu tun, "ich will um die Ansicht zu ändern," scheint sehr fraglich. Die bessere Methode ist, meiner Meinung nach, wäre für das Objekt, das hält den Blick zu ersetzen, der dieser Ansicht.
Natürlich, du bist mit RAII-Objekten, die Sie nicht wirklich brauchen, rufen Sie löschen auf alle...richtig?
InformationsquelleAutor Crazy Eddie
Dies ist der Kern-idiom für Referenz-Objekte gezählt.
Reference-counting ist eine starke form der deterministische garbage collection - es sorgt Objekte verwalten Ihr EIGENES Leben, anstatt sich auf "intelligente" Zeiger, etc. um es für Sie tun. Das zugrunde liegende Objekt wird immer nur der Zugriff über "Verweis" intelligente Zeiger, entworfen, so dass die Zeiger, Inkrementieren und Dekrementieren Mitglied integer (reference count) in das eigentliche Objekt.
Wenn der Letzte Verweis Tropfen aus dem Stapel oder gelöscht wird, wird der Referenzzähler wird auf null gesetzt. Ihr Objekt ist default-Verhalten wird dann ein Aufruf von "löschen", um Müll zu sammeln - die Bibliotheken, die ich schreiben einen geschützten virtuellen "CountIsZero" Anruf in der Basis-Klasse, so dass Sie können dieses Verhalten außer Kraft setzen, für Dinge wie caching.
Den Schlüssel zu diesem safe ist nicht so dass Benutzer Zugriff auf den KONSTRUKTOR des Objekts in Frage zu stellen (damit es geschützt ist), sondern macht Sie rufen Sie einige statische member - die FABRIK - wie "statische Referenz CreateT(...)". Auf diese Weise WISSEN Sie sicher, dass Sie immer gebaut mit den normalen "neuen" und keine raw pointer ist immer verfügbar, also "löschen" nicht immer, sprengen.
Sie können auch nur den Destruktor geschützt zu verbieten, statische und stack Zuweisungen von Ihrem Objekt.
InformationsquelleAutor Zack Yezek
Dies ist eine alte, beantwortet, Frage, aber @Alexandre fragte, "Warum sollte jemand dies tun wollen?", und ich dachte, ich könnte vielleicht geben ein Beispiel, dass ich überlege, heute Nachmittag.
Legacy-code. Nutzt nackt Zeiger Obj*obj mit einer delete obj am Ende.
Leider brauche ich manchmal, nicht oft, wenn das Objekt länger Leben.
Überlege ich, dass es eine Referenz gezählt smart-pointer. Aber es wäre viele code ändern, wenn ich
ref_cnt_ptr<Obj>
überall. Und wenn Sie mischen nackt Obj* und ref_cnt_ptr, Sie können das Objekt wird implizit gelöscht, wenn die Letzte ref_cnt_ptr Weg geht, auch wenn es Obj* noch am Leben.So, ich bin denken über das erstellen einer explicit_delete_ref_cnt_ptr. I. e. ein Verweis gezählt Zeiger, wo das löschen ist nur möglich in einer expliziten delete-routine. Sie es in einen Ort, an dem Sie den vorhandenen code kennt die Lebensdauer des Objekts, als auch in meinem neuen code, bleibt das Objekt länger Leben.
Inkrementieren und Dekrementieren die Referenz-Zählung als explicit_delete_ref_cnt_ptr bekommen manipuliert.
Aber NICHT befreien, wenn der Verweiszähler gesehen, dass die null in der explicit_delete_ref_cnt_ptr Destruktor.
Nur befreien, wenn der Verweiszähler gesehen, dass die null in eine explizite löschen-wie Betrieb. E. g. in etwas wie:
OK, sowas in der Art. Es ist ein bisschen ungewöhnlich, einen Verweis gezählt Zeiger-Typ nicht automatisch löschen Sie das Objekt wies in der rc ' ed, ptr-Destruktor. Aber es scheint, wie es könnte mischen nackt Zeiger und rc ' ed Zeiger ein bisschen sicherer.
Aber bisher keine Notwendigkeit, löschen Sie diese.
Aber dann fiel es mir auf: wenn das Objekt wies nach, der pointee, weiß, dass es als Verweis gezählt werden, z.B. wenn die Zählung innerhalb des Objekts (oder in irgendeiner anderen Tabelle), dann die routine delete_if_rc0 könnte eine Methode der pointee-Objekt, nicht den (smart -) pointer.
Tatsächlich, es doesn ' T müssen eine member-Methode an alle, konnte aber eine freie Funktion:
(BTW, ich weiß, der code ist nicht ganz richtig - es wird weniger lesbar, wenn ich all die details, so lasse ich es so.)
InformationsquelleAutor Krazy Glew
Löschen, das ist legal, solange Objekt im heap.
Sie müssten erfordern Objekt-heap nur.
Der einzige Weg das zu tun ist, stellen Sie den Destruktor geschützt werden, so löschen Sie können NUR aufgerufen werden, aus der Klasse , so müssten Sie eine Methode, die sicherstellen würde, Löschung
InformationsquelleAutor Swift - Friday Pie