2010-04-13 21 views
17

Disculpas si la pregunta suena tonta, estaba siguiendo a expertos en SO y probando algunos ejemplos yo mismo, y este es uno de ellos. Intenté la opción de búsqueda pero no encontré una respuesta para este tipo.¿Por qué el destructor de la clase se llama dos veces?

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

¿Por qué el destructor de la clase se llama dos veces?

+0

No crea que SO admita la etiqueta ''. Sin embargo, tal vez una solicitud de función en meta? ¡Creo que a Jeff le encantará! :-) –

+0

@pst: Gracias, estaba haciendo la edición y antes de que pudiera guardarla, estaba hecho. – dicaprio

+5

Solo me pregunto, ¿por qué esta wiki de la comunidad? – jasonline

Respuesta

39

Para agregar el elemento, se invoca un constructor de copia en un objeto temporal. Después del push_back(), se destruye el objeto temporal; esa es la primera llamada al destructor. Luego, la instancia vector sale del alcance y destruye todos los elementos almacenados: esa es la segunda llamada al destructor.

+0

@ sharptooth & @Andreas: Gracias. Lo intenté después de ver tu respuesta, definí un constructor de copia A (ConstA &) y sí se llamó. – dicaprio

+3

@dicaprio: Claro, hasta que haya definido su propio constructor de copia, el compilador utilizó su propio constructor de copia generado automáticamente. – sharptooth

4

Se llama al destructor una vez cuando se destruye el temporal enviado a push_back y cuando se destruye el elemento en t.

19

Esto le mostrará lo que es 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: Intenté lo mismo justo antes de publicar esto, entendí el punto, ¡gracias! – dicaprio

0

Lo más probable, es cada vez creado copia de su objeto. Por lo tanto, el destructor para el objeto copiado y para el objeto original hace el conteo de llamadas = 2.

Ejemplo: Aunque está pasando la referencia del objeto a alguna clase, esto internamente invocaría el constructor de copia. Para evitar esto, la clase hija (a la que está pasando la referencia de los padres, debe ser lo más;

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

Entonces, el objeto principal será pasado como;

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

Además, puede depurar la invocación constructor de copia, anulando;

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

Más información @[email protected]

1

Hay dos llamadas a destructor porque hay dos objetos: el argumento push_back y el elemento recién agregado dentro de vectort.

STL containers copias de la tienda. En su ejemplo, el elemento agregado al vector por push_back es una copia construida a partir del argumento pasado a push_back. El argumento es A(), que es un objeto temporal, vea here (variant 4).

Ampliando un poco la respuesta, aunque no lo haya solicitado explícitamente: puede ser útil saber cuándo se destruye el temporal. El estándar (N4140) Las EFS bastante claramente en 12.2 p3:

... Los objetos temporales se destruyen como el último paso en la evaluación de la -expresión completa (1.9) que (léxico) contiene el punto en el que fueron creados ...

Nota al margen: Si utiliza emplace_back, hay un solo objeto. El nuevo elemento en el contenedor se construye directamente a partir de los argumentos para emplace_back. Muchos contenedores STL aprendieron una variante de escenario en C++ 11.

Cuestiones relacionadas