2010-11-21 6 views
6

Warum würde man explizit die Vektorelementvariable (von on in einem dtor löschen (siehe Code unten). Was sind die Vorteile des Löschens des Vektors, obwohl es direkt nach der letzten Zeile von dtor zerstört wird Code ausgeführt werden sollenMuss ich eine Membervariable im Destruktor ungültig machen?

class A 
{ 
~A() 
{ 
    values.clear(); 
} 

private: 
    std::vector <double> values_; 
}; 

ähnliche Fragen zu einem der folgenden Code:

class B 
{ 
~B() 
{ 
    if (NULL != p) 
    { 
     delete p_; 
     p_ = NULL; 
    } 
} 

private: 
    A * p_; 
}; 

Da es keine Möglichkeit gibt, die dtor zweimal aufgerufen wird erhalten, warum p_ dann zunichte zu machen

+0

Hallo Michael, du solltest versuchen, deinen Titel aufzuräumen. Sie werden auf diese Weise mehr Antworten erhalten. –

+1

Michael FTFY. Wenn Sie meinen, dass meine Bearbeitung schlecht war, können Sie sie gerne wiederherstellen. –

Antwort

11

In? Klasse A gibt es absolut keinen Grund für .clear() die vector-Typ-Mitgliedsvariable im Destruktor. Die vector Destruktor wird .clear()vector, wenn es aufgerufen wird. Es besteht keine Notwendigkeit zu prüfen, ob p_ != NULL zuerst, weil delete NULL; ist definiert als ein No-op

delete p_; 

:

In der Klasse B kann der Bereinigungscode einfach als geschrieben werden. Es ist auch nicht notwendig, p_ = NULL zu setzen, nachdem Sie delete d es haben, weil p_ nicht mehr legitim zugegriffen werden kann, nachdem das Objekt, von dem es ein Mitglied ist, zerstört wird.

Das gesagt, sollten Sie selten delete in C++ Code verwenden müssen. Sie sollten das Scope-Bound Resource Management (SBRM, auch Ressourcenerwerbsinitialisierung genannt) verwenden, um die Ressourcenlebensdauer automatisch zu verwalten.

In diesem Fall könnten Sie einen intelligenten Zeiger verwenden. boost::scoped_ptr und std::unique_ptr (von C++ 0x) sind beide gute Möglichkeiten. Keiner von beiden sollte einen Overhead haben, verglichen mit der Verwendung eines rohen Zeigers. Darüber hinaus unterdrücken beide die Generierung des implizit deklarierten Kopierkonstruktors und des Kopierzuweisungsoperators, was normalerweise der Fall ist, wenn Sie eine Membervariable haben, die ein Zeiger auf ein dynamisch zugewiesenes Objekt ist.

+4

Schöne Antwort mit Ausnahme des Codes "selten in C++ löschen". Ich stimme zu, dass Dinge wie auto_ptr und unique_ptr viele Situationen betreffen, in denen es absolut falsch ist zu sagen, dass "delete" sollte/selten/verwendet werden. –

+5

@edA: Nein, nicht wirklich. Es sollte selten verwendet werden. Geben Sie uns eine Situation, in der Sie denken, dass Sie sie brauchen, wir machen sie sauberer und sicherer. ** Alle ** Ressourcen sollten umgebrochen werden, sodass Sie nur den Wrapper verwenden müssen. Wenn Sie irgendwo neben einem Destruktor ein 'delete 'haben, haben Sie es falsch gemacht – GManNickG

+5

@edA: Ich stehe zu dieser Aussage. Ich habe in den letzten zwei Jahren keinen 'delete'-Ausdruck in neuen Produktionscode geschrieben (vorher war ich ein kompletter Anfänger, wenn es darum ging, korrekten C++ - Code zu schreiben). –

0

Im Fall p_, gibt es keine Notwendigkeit, es gleich Null in dem destructor zu setzen, aber es kann ein nützlicher Abwehrmechanismus sein. Stellen Sie sich einen Fall vor, in dem Sie einen Fehler haben und nach dem Löschen noch einen Zeiger auf ein B-Objekt enthält:

Wenn es versucht, das B-Objekt zu löschen, verursacht p_, das null ist, dass das zweite Löschen harmlos ist ein Haufen Korruption.

Wenn es versucht, eine Methode für das B-Objekt aufzurufen, verursacht p_, das null ist, sofort einen Absturz. Wenn p_ immer noch der alte Wert ist, sind die Ergebnisse undefiniert, und es kann schwierig sein, die Ursache des resultierenden Absturzes zu finden.

+0

Das sollte nie ein Problem sein. Wenn mehrere Dinge auf etwas verweisen, sollte das etwas in ein 'shared_ptr' gebracht haben. Problem gelöst. – GManNickG

+2

Wenn Sie wirklich einen Fehler haben, wird der Fehler durch Setzen des Zeigers auf Null ausgeblendet. Willst du das wirklich? Nein, du willst es so schnell wie möglich fürchterlich zum Absturz bringen. – fredoverflow

+0

@Fred, ja, aber die Einstellung wird nicht dazu führen. Haben Sie versucht, einen doppelten Löschfehler aufzuspüren? Sie machen keinen Spaß. –

2

In Ihrem zweiten Beispiel gibt es keinen Grund, p_ auf Null zu setzen, insbesondere weil es im Destruktor gemacht wird, was bedeutet, dass die Lebensdauer von p_ sofort danach endet.

Darüber hinaus ist es sinnlos, p_ mit null zu vergleichen, bevor delete aufgerufen wird, da delete Ausdruck diese Überprüfung intern durchführt. In Ihrem spezifischen künstlichen Beispiel sollte der Destruktor einfach delete p_ enthalten und sonst nichts bemerken. Nein if, keine Einstellung p_ auf Null.

Verwandte Themen