Frage

Heute habe ich einige Legacy-Code zu sehen. Im destructor gibt es eine Aussage wie „delete this“. Denke ich, wird dieser Aufruf rekursiv sein. Warum es funktioniert?

Ich habe einige schnelle Suche auf Y !, Ich fand, dass, wenn es eine Notwendigkeit, um den Benutzer zu beschränken ist, das Stapel-Objekt zu erstellen, können wir destructor private und bieten eine Schnittstelle machen die Instanz zu löschen. In der Schnittstelle vorgesehen ist, müssen wir uns auf diesem Zeiger löschen nennen.

Gibt es andere Situationen für solche Aussagen mit?

War es hilfreich?

Lösung

„Löschen dieses“ allgemein für ref verwendet wird gezählt Objekte. Für einen ref gezählt Objekt der Entscheidung, wann löscht in der Regel auf dem Objekt selbst platziert wird. Hier ist ein Beispiel dafür, was eine Release-Methode aussehen würde [1].

int MyRefCountedObject::Release() {
  _refCount--;
  if ( 0 == _refCount ) {
    delete this;
    return 0;
  }
  return _refCount;
}

ATL COM-Objekte sind ein gutes Beispiel für dieses Muster.

[1] Ja, ich weiß, das ist nicht Thread-sicher.

Andere Tipps

delete this ist in einem Destruktor nicht gültig. Es kann an anderer Stelle verwendet werden. Aber es ist nur selten eine gute Idee. Der wxWidgets Framework verwendet sie für ihre Thread-Klasse. Es hat einen Modus, in dem, wenn der Thread-Ausführung endet, es Systemressourcen automatisch freigibt und sich selbst (die wxThread Objekt). Ich fand es sehr ärgerlich, weil von außen, kann man nicht wissen, ob es gültig ist darauf zu beziehen oder nicht - Sie können nicht eine Funktion wie IsValid mehr nennen können, weil das Objekt nicht existiert. Das riecht wie das Hauptproblem bei delete this, abgesehen von dem Problem, dass es nicht für nicht-dynamische Objekte verwendet werden.

Wenn Sie es tun, stellen Sie sicher, dass Sie keine Daten-Mitglied berühren, oder rufen Sie jede Memberfunktion mehr auf dem Objekt, das Sie auf diese Weise gelöscht. Beste tun, es als letzte Anweisung in einer nicht-virtuellen, geschützten oder privaten Funktion. löscht Aufruf ist auch in einer virtuellen und / oder öffentlichen Funktion gültig ist, aber ich würde die Sichtbarkeit des Verfahrens tun, dass beschränken.

Der C ++ FAQ hat einen Eintrag darüber. C ++ Standard-Zitat auf meinem Anspruch oben (3.8p5):

  

Bevor die Lebensdauer eines Objekt begonnen hat, aber nach der Lagerung, die das Objekt wurde occupy oder zugewiesen, nachdem die Lebensdauer eines Objekts beendet ist und vor der Lagerung, die das Objekt besetzt wieder verwendet oder freigegeben, jeden Zeiger, verweist auf den Speicherort, wo das Objekt wird oder befand mich aber nur in begrenzten Weise genutzt werden kann. [...] Wenn das Objekt ist oder war ein Klasse-Typ mit einem nicht-trivial destructor, und der Zeiger wird als Operand eines Löschausdruckes verwendet, hat das Programmverhalten nicht definiert.

Lebenszeit endet, wenn der Destruktor der Objektausführung beginnt. Hinweis gibt es Ausnahmen von den Regeln nach diesem Absatz kommen für Objekte im Bau und Zerstörung (Sie dürfen nicht-statische Datenelemente zuzugreifen, zum Beispiel), detailliert auf 12.7.

Es wurden gute Gründe angesehen werden diese ++ Tage in den frühen C zu tun. Zum Beispiel löscht das Selbst eines ref gezählt Objekts (wie JaredPar sagt). Soweit ich weiß, sie haben alle gefunden worden, auf lange Sicht eine schlechte Idee zu sein.

in einer doppelt verknüpften Liste, dann ist es möglich, einen Knotenpunkt zu entfernen, ohne fremde Struktur Referenzierung, wie beispielsweise das High-Level „Liste“ Objekt. Dies macht es für jeden Knoten seine eigene angemessene Deallokation zu handhaben (möglicherweise in Verbindung mit einer komplementären statischen Methode die anfängliche Zuweisung aus dem gleichen Pool von Speichern zu handhaben). In dieser Situation könnte es sinnvoll für das Node-Objekt macht selbst zu löschen (wenn vom Benutzer angefordert).

void RemoveAndDeallocate()
{
    LinkedListNode *current_prev = prev, *current_next = next;
    current_prev->next = current_next;
    current_next->prev = current_prev;
    delete this;
}

Obwohl, es ist auch sinnvoll für einen Knoten aus einer Liste und verknüpfen in einer anderen Liste nicht verknüpft werden, ohne Speicher-ausplanen, so ist es nicht wünschenswert, dass eine einzelne Entfernungsoperation bedingungslos den Speicher frei.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top