2010-04-13 3 views
17

Excuses si la question semble stupide, je suivais des experts en SO et en essayant quelques exemples moi-même, et c'est l'un d'entre eux. J'ai essayé l'option de recherche mais je n'ai pas trouvé de réponse pour ce genre.Pourquoi le destructeur de la classe est-il appelé deux fois?

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. 
} 

Pourquoi le destructeur de la classe est-il appelé deux fois?

+0

Ne pensez pas que SO supporte la balise ''. Cependant, peut-être une demande de fonctionnalité sur Meta? Je pense que Jeff va l'adorer! :-) –

+0

@pst: Merci, je faisais l'édition et avant que je puisse l'enregistrer, ça a été fait. – dicaprio

+5

Je me demandais juste pourquoi ce wiki communautaire? – jasonline

Répondre

39

Pour ajouter l'élément, un constructeur de copie est appelé sur un objet temporaire. Après le push_back() l'objet temporaire est détruit - ce n'est pas le premier appel de destructeur. Alors l'instance vector sort de la portée et détruit tous les éléments stockés - c'est le deuxième appel de destructeur.

+0

@ sharptooth & @Andreas: Merci. J'ai juste essayé après avoir vu votre réponse, j'ai défini un constructeur de copie A (ConstA &) et oui il s'appelle. – dicaprio

+3

@dicaprio: Bien sûr, jusqu'à ce que vous définissiez votre propre constructeur de copie, le compilateur utilisait son propre constructeur de copie généré automatiquement. – sharptooth

4

Le destructeur est appelé une fois lorsque le message temporaire envoyé à push_back est détruit et une fois lorsque l'élément t est détruit.

19

Cela va vous montrer ce qui est happening:

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: J'ai essayé la même chose juste avant de poster ceci, j'ai compris, merci !! – dicaprio

0

Très probablement, copie de votre objet est créé obtenir. À cause de cela, le destructeur pour l'objet copié, et pour l'original-object fait le call-count = 2. Exemple: Bien que vous passiez la référence d'objet à une classe, cela invoquerait en interne le constructeur de copie. Pour éviter cela, la classe enfant (à laquelle vous passez la référence parent, doit être aussi;

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

Ensuite, l'objet parent sera passé comme,

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

De plus, vous pouvez déboguer le invokation constructeur de copie, en remplaçant,

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

Plus d'info @[email protected]

1

Il existe deux appels de destructeur car il existe deux objets: l'argument push_back et l'élément nouvellement ajouté au sein de vectort.

STL containers stocker des copies. Dans votre exemple, l'élément ajouté au vector par push_back est une copie construite à partir de l'argument passé à push_back. L'argument est A(), qui est un objet temporaire, voir here (variant 4).

En développant la réponse un peu, même si vous ne l'avez pas explicitement demandé: il peut être utile de savoir quand le temporaire est détruit. La norme (N4140) SAIS il assez clairement 12.2 p3: objets

... temporaires sont détruits comme la dernière étape dans l'évaluation de la pleine expression (1.9) que (lexicalement) contient le point où ils ont été créés ...

Note de côté: Si vous utilisez emplace_back, il n'y a qu'un seul objet. Le nouvel élément du conteneur est directement construit à partir des arguments de emplace_back. De nombreux conteneurs STL ont appris une variante d'emplace en C++ 11.

Questions connexes