c++ - implementar - destructor tortugas ninja
¿Por qué el destructor de la clase se llama dos veces? (5)
Disculpas si la pregunta suena tonta, estaba siguiendo a los expertos en SO y probando algunos ejemplos yo mismo, y este es uno de ellos. Probé la opción de búsqueda pero no encontré una respuesta para este tipo.
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?
Esto te mostrará lo que 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());
}
Hay dos llamadas de destructor porque hay dos objetos: el argumento de push_back
y el elemento recién agregado dentro del vector
t
.
Los contenedores STL almacenan copias. En su ejemplo, el elemento agregado al vector
mediante push_back
es una copia construida a partir del argumento pasado a push_back
. El argumento es A()
, que es un objeto temporal, consulte aquí (variante 4) .
Ampliando un poco la respuesta, aunque no la hayas pedido explícitamente: puede ser útil saber cuándo se destruye lo temporal. El estándar ( N4140 ) lo N4140 claramente en 12.2 p3:
... Los objetos temporales se destruyen como último paso en la evaluación de la expresión completa (1.9) que (léxicamente) contiene el punto donde se crearon ...
Nota al emplace_back
: si usas emplace_back
solo hay un 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 emplace en C ++ 11.
Lo más probable es que la copia de su objeto se está creando. Debido a lo cual, el destructor para el objeto copiado y el objeto original hace que el recuento de llamadas sea = 2.
Ejemplo: Aunque está pasando la referencia de objeto, a alguna clase, esto invocaría internamente el constructor de copia. Para evitar esto, la clase secundaria (a la que está pasando la referencia principal, debe ser como;
Parent *const &p parentRef; //Child.h
Entonces, el objeto padre se pasará como;
// Parent.cpp
Parent *parentObj = this;
Child *childObj = Child(parentObj);
Además, puede depurar la invocación de copia-constructor, anulando;
Parent(const Parent& object){
cout <<"copy called.." << endl;
}
...
Más información @@
Para agregar el elemento, se invoca un constructor de copia en un objeto temporal. Después de push_back()
el objeto temporal se destruye, esa no es la primera llamada del destructor. Luego, vector
instancia de vector
queda fuera del alcance y destruye todos los elementos almacenados, esa es la segunda llamada del destructor.
Se llama al destructor una vez cuando se destruye el envío temporal a push_back
y una vez cuando se destruye el elemento en t
.