In meinen ersten grundlegenden Tests ist es vollkommen sicher, dies zu tun. Es ist mir jedoch aufgefallen, dass der Versuch, this
später in einer Funktion zu manipulieren, dass delete
s this
ein Laufzeitfehler sein könnte. Ist das wahr und ist es normalerweise sicher zu delete this
? oder gibt es nur bestimmte Fälle, in denen es sicher ist?Ist es sicher, das zu löschen?
Antwort
delete this
ist legal und tut was Sie erwarten würden: es ruft den Destruktor Ihrer Klasse auf und befreit den zugrunde liegenden Speicher. Nach delete this
zurückgibt, Ihr this
Zeiger Wert nicht ändern, so dass es jetzt ein dangling Zeiger ist, sollte nicht dereferenziert werden. Dies schließt die implizite Dereferenzierung mit den Membervariablen der Klasse ein.
Es wird in der Regel in Bezug gezählt Klassen gefunden, wenn die Referenzzählung auf 0 verringert wird, die DecrementRefCount()
/Release()
/was auch immer Memberfunktion aufruft delete this
.
delete this
wird aus vielen Gründen als sehr schlechte Form angesehen. Es ist leicht, nach delete this
versehentlich auf Mitgliedsvariablen zuzugreifen. Der Anrufercode erkennt möglicherweise nicht, dass sich Ihr Objekt selbst zerstört hat.
Auch delete this
ist ein "Code-Geruch", dass Ihr Code möglicherweise keine symmetrische Strategie für Objektbesitz hat (wer zuweist und wer löscht).
Ein Objekt konnte sich
new
nicht selbst zugewiesen haben, also bedeutet Aufruf
delete this
, dass Klasse A ein Objekt zuweist, aber Klasse B gibt es später frei [self].
Technisch ist Ihr letzter Absatz falsch. Obwohl es zutrifft, dass ein Objekt sich nicht selbst zugewiesen haben kann, impliziert dies nicht, wohin Sie als nächstes gehen. Es folgt daher nicht, dass eine andere Klasse es zugewiesen hat. Eine statische Factory-Methode für dieselbe Klasse könnte die Erstellung ausgeführt haben. –
"Löschen Sie dies wird aus vielen Gründen in der Regel als sehr schlechte Form betrachtet." Ich denke, das ist der Grund, warum gut gestaltete ref-gezählte Klassen diese nicht löschen; . Sie verwenden den Griff/Körper Idiom. Meiner Meinung nach ist das Löschen fast immer eine schlechte Idee. (Nun, ich weiß * keinen * Grund - aber ich bin vorsichtig) –
Sie erwähnen nicht [Sie können nicht 'löschen dies 'in einem Destruktor] (http://stackoverflow.com/a/447531/111307). – bobobobo
Ja. Es sollte vollkommen in Ordnung sein. "Dies" ist nur ein Zeiger. Jeder Zeiger wird für das Löschen tun. Die Informationen zum Löschen eines Objekts sind in den Heap-Datensätzen enthalten. So wird IUnknown :: Release() normalerweise in COM-Objekten implementiert.
Es ist sicher, "this" zu löschen, solange es im Wesentlichen die letzte Operation in der Methode ist. In der Tat tun dies mehrere professionelle APIs (siehe die CComObject-Implementierung von ATL für ein Beispiel).
Die einzige Gefahr besteht darin, nach dem Aufruf von "delete this" auf andere Mitgliederdaten zuzugreifen. Dies ist sicherlich unsicher.
Es besteht auch die Gefahr, 'delete this' in einem Destruktor aufzurufen – bobobobo
Read für eine ähnliche Diskussion. Ihr Verständnis ist richtig, dass es funktioniert, benötigt wird und gefährlich sein kann, da Sie danach nicht darauf zugreifen können.
löschen Dies kann zu einem Problem führen, wenn Sie Unterklassen des Objekts haben, das Sie löschen. Denken Sie daran, dass die Konstruktion von oben nach unten beginnt und die Löschung von unten beginnt. Wenn Sie also in der Mitte der Hierarchie löschen, haben Sie im Grunde alle Objekte unter dieser bestimmten Klasse verloren.
löschen Dies ist sehr praktisch, wenn Sie ein Objekt mit Referenzzählung implementieren, ein Beispiel dafür sind die COM-Klassen.
Was meinst du damit, wenn du sagst: "Du hast im Grunde alle Objekte unter dieser bestimmten Klasse verloren? Kannst du das erklären? Vielleicht ein Beispiel? –
Dein Beispiel ist nur wahr, wenn du keinen virtuellen Destruktor benutzt Sie sind völlig richtig, aber andererseits ist eine Hierarchie ohne virtuelle Destruktoren pure Bösheit, also sollte man es nie "sehen". –
Löschen Sie dies ist völlig legal, wie andere bereits erwähnt haben. Es ist riskant für einen zusätzlichen Grund, der noch nicht erwähnt wurde - Sie gehen davon aus, dass das Objekt auf dem Heap zugeordnet wurde. Dies kann schwierig zu garantieren sein, obwohl im Falle von Referenzzählungsimplementierungen im Allgemeinen kein Problem besteht.
Großartiger Punkt. "delete this" sollte nur dann gemacht werden, wenn Sie sicher wissen, wie das Objekt erstellt wurde Dies bedeutet normalerweise, einen privaten Konstruktor irgendeiner Art zu haben. –
In meinem Fall befindet es sich in einer Zustandsmaschine, wenn also der aktuelle Zustand fertig ist, erzeugt es einen neuen Zustand und ersetzt den einzigen Zeiger darauf im Zustandshandler und dann lösche das selbst. –
Die "richtige" Lösung ist ein privater Destruktor, der das Objekt dann aufrufen kann, um dies zu löschen, aber keine stack-basierte Version. – hacken
Wie von anderen angegeben, löschen Sie dies ist ein gültiges Idiom, aber damit es sicher ist, müssen Sie sicherstellen, dass das Objekt nie auf dem Stapel instanziiert wird.
Eine Möglichkeit, dies zu tun, ist sowohl der Konstruktor und der Destruktor privaten und erzwingen Objekterstellung durch eine Klasse Factory-Funktion zu machen, die auf dem Heap den das Objekt erstellt und gibt einen Zeiger auf sie. Die Klassenfabrik kann eine statische Elementfunktion oder eine Freundfunktion sein. Die Bereinigung kann dann über eine Delete() - Methode für das Objekt durchgeführt werden, das "delete this" ausführt. COM-Objekte funktionieren grundsätzlich so, außer dass sie zusätzlich mit dem "delete this" -Ziffer gezählt werden, der auftritt, wenn der Referenzzähler auf Null dekrementiert wird.
aber tun Sie es nicht im Destruktor!
... oder im Konstruktor :) – Constantin
Ja, das wäre schlecht. –
im Konstruktor können Sie es tun, es sei denn, Klasse hat nicht-trivialen Destruktor – 4pie0
Legal Ja
Sicher Nein
Wenn Sie von einer Basisklasse erben und gab diese in der Funktion der Basisklasse löschen, abgeleitete Klasse Zeiger verwendet, wird zu einem Absturz führen. Z. B:
class Base
{
virtual void Release()
{
delete this;
}
}
class Derived : public Base
{
void Foo()
{
...
}
}
main()
{
Base *ptrDerived = new Derived();
ptrDerived->release();
ptrDerived->Foo() //Crash
}
Was haben Sie erwartet? Jede Verwendung eines gelöschten Objekts ist UB, daher Absturz oder Schlimmeres. Dies ist nicht spezifisch für das "Löschen". Haben Sie irgendwie erwartet, dass der 'Abgeleitete' Teil des Objekts am Leben bleibt? Dann wissen Sie nichts über die Lebensdauer von C++ - Objekten. Also, was ist das: 'Release()' oder 'release()'? –
Es gilt schlechte Praxisdelete this
zu verwenden.
jedoch, falls verwendet, müssen folgende Punkte berücksichtigt werden:
1. Der delete
Operator nur für Objekte arbeitet new
Betreiber zugewiesen werden. Wenn das Objekt mit new
erstellt wird, können wir delete this
tun, sonst ist das Verhalten undefiniert.
class A {
public:
void fun(){
delete this;
}
};
int main(){
/* Following is valid */
A *ptr = new A;
ptr->fun();
ptr = NULL // make ptr NULL to make sure that things are not accessed using ptr.
/* And following is invalid: Undefined Behavior */
A a;
a.fun();
return 0;
}
2. Sobald delete this
getan wird, wird jedes Mitglied des gelöschten Objekts sollte nicht nach dem Löschen zugegriffen werden.
class A {
int x;
public:
A() {
x = 0;
}
void fun() {
delete this;
/* Invalid: Undefined Behavior */
cout<<x;
}
};
- 1. Überprüfen Sie, ob es sicher ist, eine Zeile zu löschen
- 2. Ist es sicher, Druids Ordner zu löschen? Var/tmp
- 3. Ist es sicher zu werfen volatile?
- 4. Passwortverifizierung; Ist das so sicher?
- 5. Ist es sicher, `release` für das Debuggen zu überschreiben?
- 6. Ist es sicher, Benutzern das Bearbeiten von CSS zu erlauben?
- 7. Ist es sicher, Makroaufrufe zu verschachteln?
- 8. Ist es sicher, Capistrano zu benutzen?
- 9. Ist es sicher, BenutzerregEx zu verwenden?
- 10. Wann ist es sicher, .toString() zu verwenden?
- 11. Ist es sicher, hypot() zu kaskadieren?
- 12. Ist es sicher, Pip mit einem Git Repo zu verwenden?
- 13. Subversion, ist es sicher, MergeInfo von einer Reintegratzusammenführung zu entfernen
- 14. Meteor - Wie sicher ist es?
- 15. Konstruktorproblem delegieren - Ist es sicher?
- 16. Mongoose Versionierung: Wann ist es sicher, es zu deaktivieren?
- 17. -Fomit-Frame-Zeiger, ist es sicher, es zu benutzen?
- 18. Wessen Verantwortung ist es zu löschen
- 19. Ist es sicher, den Inhalt von ~/Library/Developer/Xcode/iOS Device Logs zu löschen?
- 20. Ist es sicher, Ergebnis der Ceil zu Integer zu werfen?
- 21. Ist es sicher, ein POD-Objekt durch einen Zeiger auf seine Basis zu löschen?
- 22. Ist es sicher, die 3 Standarddatenbanken zu löschen, die während einer PostgreSQL-Installation erstellt wurden?
- 23. Ist es sicher, einen Clustered-Index in SQL Server zu löschen?
- 24. Ist es sicher, diese Python-Dateien aus/usr/bin zu löschen?
- 25. Ist es sicher/möglich, Code aus der Tabelle dba_source in Oracle 10g zu löschen?
- 26. Ist es sicher, das CSRF-Token auf derselben Seite wie das gesicherte Formular zu generieren?
- 27. Ist es sicher, eine Gabel eines GitHub Repo zu löschen, wenn sich das Original auf meine bezieht?
- 28. Ist java.io.BufferedOutputStream sicher zu verwenden?
- 29. Ist es sicher, Schlösser und Verriegelungen zu mischen?
- 30. Ist es sicher, va_list in ausnahmesicherem Code zu verwenden?
stimme ich nicht zu. Die zwei Fragen verbunden zu fragen nach einem bestimmten Fall und wenn man dies verwenden würde löschen. Ich frage, ob es im allgemeinen Sinn sicher ist und wann nicht. –