2010-04-13 12 views
17

Entschuldigung, wenn die Frage albern klingt, folgte ich Experten in SO und versuchte einige Beispiele selbst, und das ist einer von ihnen. Ich habe die Suchoption versucht, aber keine Antwort für diese Art gefunden.Warum wird der Destruktor der Klasse zweimal aufgerufen?

class A 
{ 
    public: 
     A(){cout<<"A Contruction"<<endl;} 
     ~A(){cout<<"A destruction"<<endl;} 
}; 

int main() 
{ 
    vector<A> t; 
    t.push_back(A()); // After this line, when the scope of the object is lost. 
} 

Warum wird der Destruktor der Klasse zweimal aufgerufen?

+0

Glauben Sie nicht, dass SO das '' Tag unterstützt. Obwohl, vielleicht eine Feature-Anfrage auf Meta? Methinks Jeff wird es lieben! :-) –

+0

@pst: Danke, ich habe den Schnitt gemacht und bevor ich es speichern konnte, war es erledigt. – dicaprio

+5

Ich frage mich nur, warum ist dieses Community-Wiki? – jasonline

Antwort

39

Zum Hinzufügen des Elements wird ein Kopierkonstruktor für ein temporäres Objekt aufgerufen. Nach dem push_back() ist das temporäre Objekt zerstört - das ist der erste Destruktor-Aufruf. Dann vector Instanz geht aus dem Geltungsbereich und zerstört alle gespeicherten Elemente - das ist der zweite Destruktor Aufruf.

+0

@ shorttooth & @Andreas: Danke. Ich habe gerade versucht, nachdem ich Ihre Antwort gesehen habe, habe ich einen Kopierkonstruktor A (ConstA &) definiert und ja es wird aufgerufen. – dicaprio

+3

@dicaprio: Sicher, bis Sie Ihren eigenen Kopierkonstruktor definiert haben, verwendete der Compiler seinen eigenen, automatisch generierten Kopierkonstruktor. – sharptooth

4

Der Destruktor wird einmal aufgerufen, wenn das temporäre push_back zerstört wird und wenn das Element in t zerstört wird.

19

Dies wird Ihnen zeigen, was happening ist:

struct A { 
    A() { cout << "contruction\n"; } 
    A(A const& other) { cout << "copy construction\n"; } 
    ~A() { cout << "destruction\n"; } 
}; 

int main() { 
    vector<A> t; 
    t.push_back(A()); 
} 
+0

! Roger: Ich habe das gleiche versucht, bevor du das gepostet hast, ich habe verstanden, danke !! – dicaprio

0

wahrscheinlich die meisten, Kopie des Objekts erstellt zu werden. Daher macht der Destruktor für das kopierte Objekt und für das ursprüngliche Objekt den Aufruf-Count = 2.

Beispiel: Obwohl Sie die Objektreferenz an eine Klasse übergeben, würde dies intern den Kopierkonstruktor aufrufen. Um dies zu vermeiden, die Kind-Klasse (zu dem Sie die übergeordneten Referenz sind vorbei, muß sein,

Parent *const &p parentRef; //Child.h 

Dann wird das übergeordnete Objekt als übergeben wird;

// Parent.cpp 
Parent *parentObj = this; 
Child *childObj = Child(parentObj); 

Zusätzlich können Sie debuggen der Kopie-Konstruktor Invokation, durch zwingende;

Parent(const Parent& object){ 
     cout <<"copy called.." << endl; 
} 
... 

Mehr Infos @[email protected]

1

Es gibt zwei Destruktoraufrufe, weil zwei Objekte vorhanden sind: das Argument push_back und das neu hinzugefügte Element innerhalb vectort.

STL containers Kopien speichern. In Ihrem Beispiel ist das Element, das zu vector von push_back hinzugefügt wurde, eine Kopie, die aus dem an push_back übergebenen Argument erstellt wurde. Das Argument ist A(), das ein temporäres Objekt ist, siehe here (variant 4).

Erweitern Sie die Antwort ein wenig, obwohl Sie nicht explizit danach gefragt haben: Es könnte nützlich sein zu wissen, wann das temporäre zerstört wird. Der Standard (N4140) sais es ziemlich klar in 12,2 p3:

... Temporäre Objekte werden als letzter Schritt zerstört bei der Bewertung der Voll Ausdruck (1.9), dass (lexikalisch) enthält den Punkt, wo sie wurden erstellt ...

Seitennotiz: Wenn Sie emplace_back verwenden, gibt es nur ein Objekt. Das neue Element im Container wird direkt aus den Argumenten für emplace_back erstellt. Viele STL-Container haben in C++ 11 eine Platzierungsvariante gelernt.

Verwandte Themen