example container c++ constructor stdlist

c++ - container - Destructor solicitó un objeto al agregarlo a std:: list



queue c++ (5)

Cuando empuja hacia atrás () su objeto Foo, el objeto se copia a las estructuras de datos internas de la lista, por lo tanto se llama al Dtor y al Ctor de otra instancia.

Todos los tipos de contenedores estándar de STL en C ++ toman sus elementos por valor, por lo tanto los copian según sea necesario. Por ejemplo, cada vez que un vector necesita crecer, es posible que se copien todos los valores en el vector.

Quizás desee almacenar punteros en lugar de objetos en la lista. Al hacer eso, solo los punteros se copian en lugar del objeto. Pero, al hacerlo, debe asegurarse de eliminar los objetos una vez que haya terminado:

for (std::list<Foo*>::iterator it = list.begin(); it != list.end(); ++it) { delete *it; } list.clear();

Alternativamente, puede intentar usar algún tipo de clase de ''puntero inteligente'', por ejemplo de las bibliotecas de Boost.

Tengo un objeto Foo y una std :: list que contiene instancias de él. Mi problema es que cuando agrego una nueva instancia a la lista, primero llama al ctor pero luego también al dtor. Y luego el dtor en otra instancia (de acuerdo con este puntero).

Se agrega una sola instancia a la lista, pero dado que se llama a su dtor (junto con sus padres), el objeto no se puede usar como se espera.

Aquí hay un código simplificado para ilustrar el problema:

#include <iostream> #include <list> class Foo { public: Foo() { int breakpoint = 0; } ~Foo() { int breakpoint = 0; } }; int main() { std::list<Foo> li; li.push_back(Foo()); }


Estás creando un Foo temporal aquí:

li.push_back( Foo() )

push_back copia ese Foo en sus estructuras internas de datos. El Foo temporal se destruye después de que push_back se haya ejecutado, lo que llamará al destructor.

Necesitarás un constructor de copia adecuado que aumente el recuento de referencias en los miembros de la clase que no quieras destruir antes de tiempo o que sea privado para forzarte en la solución del puntero.


Hacer que la lista contenga punteros en lugar de instancias resuelve el problema con el llamado al destructor. Pero todavía quiero entender por qué sucede.

#include <iostream> #include <list> class Foo { public: Foo() { int breakpoint = 0; } ~Foo() { int breakpoint = 0; } }; int main() { std::list<Foo*> li; li.push_back(new Foo()); }


Lo que realmente sucede aquí es que almacena una copia del objeto pasado en la lista, porque lo está enviando por valor en lugar de por referencia. Por lo tanto, el primer dtor que se llama se llama en realidad al objeto que pasa al método push_back, pero para entonces se había creado una nueva instancia y ahora está almacenado en la lista.

Si no desea que se cree una copia del objeto Foo , guarde los punteros a los objetos Foo en la lista en lugar de los objetos mismos. Por supuesto, al hacerlo tendrá que liberar adecuadamente la memoria sobre la destrucción de la lista.


Usa este objeto para entender:

class Foo { public: Foo(int x): m_x(x) { std::cout << "Constructed Object: " << m_x << ")/n"; } Foo(Foo const& c): m_x(c.m_x+100) { std::cout << "Copied Object: " << m_x << ")/n"; } ~Foo() { std::cout << "Destroyed Object: " << m_x << ")/n"; } };

El primero principal

std::list<Foo*> li; li.push_back(Foo(1));

Aquí creamos un objeto Foo temporal y llamamos push_back (). El objeto temporal se copia en la lista y la función regresa. Al completar esta declaración, el objeto temporal se destruye (a través del destructor). Cuando se destruya la lista, también destruirá todos los obejcts que contenga (Foo es un objeto con un destructor, por lo que la destrucción incluye llamar al destructor).

Entonces deberías ver algo como esto:

Constructed Object: 1 Constructed Object: 101 DestroyedObject: 1 DestroyedObject: 101

En el segundo ejemplo tienes:

std::list<Foo*> li; li.push_back(new Foo(1));

Aquí usted crea dinámicamente un objeto en el montón. Luego llama al push_back (). Aquí el puntero se copia en la lista (el puntero no tiene constructor / destructor) por lo que no sucede nada más. La lista ahora contiene un puntero al objeto en el montón. Cuando la función retorna no se hace nada más. Cuando se destruye la lista, se destruye (tenga en cuenta la sutil diferencia entre los que se destruyen y eliminan) el objeto que contiene (un puntero) pero un puntero no tiene destructor, por lo que no ocurre nada, se perderá memoria.

Entonces deberías ver algo como esto:

Constructed Object: 1