2012-05-28 13 views
5

mögliche Dubletten:
C++: Delete this?
Object-Oriented Suicide or delete this; Konnte ein Objekt seinen Speicher freigeben?

Ich lerne C++ durch das sehr gute Buch C++ Primer zu lesen und ich lerne, wie C++ Speicherfreigabe Speicher durch die delete Schlüsselwörter wie C macht mit free. Java und Pascal haben diesen Mechanismus nicht, um Speicher frei zu befreien. Es könnte zu Fehlern in Programmen führen, wenn sie lange laufen und Variablen zerstört werden, die benötigt werden, damit sie nicht trivialisiert werden. Kurz

In ich frage mich, ob es in C rechtliche oder advicable zum Beispiel ist ++ für eine Variable this.delete() zu tun und selbst löschen. Wir hören meistens über das Freigeben von Zeigern in C und C++ und dies geschieht mit den neuen Schlüsselwörtern free und delete. Pascal hat auch Zeiger, aber Java nicht. Also in Java sollte es nicht möglich sein, da Sie nicht explizit Objekte löschen, C hat keine Objekte, so konnte struct nicht den Speicher zugewiesen werden, selbst wenn es technisch möglich war, da C keine Objekte hat und Pascal auch nicht .

Also ich lasse C++ für meine Frage, ob es für ein Objekt legal ist, sich selbst mit etwas wie this.delete() zu löschen?

+0

Doin g so ist möglich - 'delete this;' ist in C++ absolut gültige Syntax und sollte "richtig" kompilieren und ausführen. Es wird jedoch davon ausgegangen, dass "* this" im Heap zugeordnet ist, was nicht unbedingt so ist. Außerdem riskiert es eine weitere Speicherkorruption, da der zuvor von '* this' belegte Raum nach der Freigabe wieder von späteren Speicherzuweisungen verwendet werden kann. Schlechte Idee. Renn weg! Renn weg! –

Antwort

6

Es ist durchaus möglich für ein Objekt delete this; zu tun.

Allerdings ist die Verwendung von this danach ein undefiniertes Verhalten.

Also, wenn Sie sind sehr vorsichtig mit wurde danach geschehen ist, ist es in Ordnung und legal für ein Objekt „Selbstmord begeht“ von delete this;

tun Aber, es ist wirklich keine gute Idee, vor allem, weil es bedeutet, dass Ihre Klasse sollte nur durch neue eingefügt werden, da eine Zuweisung auf dem Stack dazu führen könnte, dass der Destruktor zweimal aufgerufen wird: durch das Löschen dieser und wenn außerhalb des Kontextes.

Das folgende Beispiel zeigt, warum es keine gute Idee:

class A 
{ 
public: 
    ~A() { std::cout << "Destructor"; } 
    void foo() { delete this; } 
}; 

int main() 
{ 
    { 
     A a; 
     a.foo(); // OK, a is deleted 
    } // Going out of context, the destructor is called again => undefined behavior 
    return 0; 
} 
+0

Vielen Dank für die Antwort. Ich bemerke, dass es in C++ im Vergleich zu anderen Sprachen nicht ungewöhnlich ist, "undefined beaviour" zu riskieren. –

+1

@NickRosencrantz: Es ist * extrem * ungewöhnlich, ein unbestimmtes Verhalten im Produktionscode zu riskieren. – NPE

+3

@NickRosencrantz: In den meisten anderen Sprachen ist undefiniertes Verhalten * nicht vorhanden *. In C++ sollte es wie die Pest vermieden werden, weil es definitionsgemäß unzuverlässig ist. Sie können Ihrem Programm nicht vertrauen, sobald es ein undefiniertes Verhalten eingegeben hat. – jalf

5

thisist ein Zeiger. Die richtige Syntax würde

delete this; 

sein Und ja, es ist möglich, aber es macht Ihr Objekt und Zeiger auf das Objekt unbrauchbar.

Siehe this für eine gute Lektüre.

In der Praxis ist die Verwendung dieser Technik ein Code-Geruch, es sei denn, Sie sind absolut sicher, was Sie tun.

+0

Das ist interessant und gut zu wissen. Danke für die Antwort. –

+0

@NickRosencrantz sicher, froh zu helfen! –

3

meine Frage, ob es legal ist für ein Objekt selbst wie this.delete mit etwas zu löschen()?

Technisch ist es für ein Objekt zulässig, delete this durchzuführen.Es gibt jedoch eine Reihe von sehr wichtigen Vorbehalten, die explained in the FAQ sind. Es ist auch wichtig zu verstehen, dass delete this ein sehr enges technisches Problem löst. Es löst keine großen Fragen zu Speicherverwaltung und Speicherbereinigung. Eine Richtung, die es wert ist weiter zu studieren, ist the use of smart pointers in C++.

0

Obwohl ein odd one Anwendungsfall für ein Dialogfeld sagen würde, wo der Benutzer auf OK oder was auch immer klickt, und diese Aktion das Dialogfeld selbst löschen, aber es ist legal.

Natürlich ist der this Zeiger nicht mehr gültig, also sollten Sie nicht versuchen, es zu benutzen.

0

Es ist durchaus möglich, dass ein Objekt seinen eigenen Speicher freigibt. Es wird jedoch aus offensichtlichen Gründen sehr selten verwendet.

Die gebräuchlichste Verwendung ist die Implementierung der Speicherverwaltung mit Referenzzählung. Wenn der Aufrufer release() aufruft und der Referenzzähler null erreicht, wird das Objekt gelöscht. Da dies innerhalb einer Membervariablen geschieht, verwendet es den Zeiger this, um die Instanz zu löschen (ähnlich wie Sie delete foo außerhalb des Objekts aufrufen würden). Zum Beispiel:

int release() 
{ 
    OSAtomicDecrement32(&m_refCount); 
    if (m_refCount <= 0) 
    { 
     delete this; 
    } 
    return m_refCount; 
} 

(Beachten Sie, dass die Syntax, die Sie erwähnen nicht gültig - delete ein Schlüsselwort ist, kein Verfahren und this ist ein Zeiger.), Obwohl

Es gibt mehrere Einschränkungen im Auge zu behalten . Sobald diese Löschung aufgerufen wurde, ist der Zeiger this nicht mehr gültig, und auch keiner der Datenelemente. Von diesem Punkt an können nur Nicht-Instanz-Referenzen (z. B. zu lokalen Variablen, statischen Methoden und Daten usw.) gemacht werden.

0

Eine weitere Möglichkeit für das Objekt seinen Speicher zu löschen ist etwas mit Ist Ressource namens Aquisition Initialisation RAII

Mit dieser Methode Sie nicht new oder delete das Objekt. Destruktor wird automatisch aufgerufen, wenn es den Bereich verlässt.

heißt würden Sie verwenden RAII in einer Funktion wie:

void foo()

{

`Object a;` 

    `int i = a.SomeMethod();` 

    `// a's destructor automatically gets called when the function is out of scope` 

}

Further Reading

Verwandte Themen