¿Borrar llama al destructor?

Tengo una clase (A) que usa una asignación de memoria de montón para uno de sus campos. La clase A se instancia y se almacena como un campo de puntero en otra clase (B).

Cuando termino con el objeto B, llamo a delete, que supongo que llama al destructor … Pero, ¿esto también llama al destructor en la clase A?

Editar:

De las respuestas, lo tomo (edite si es incorrecto):

  1. delete instancia de B llama a B :: ~ B ();
  2. que llama A::~A();
  3. and A::~A debe delete explícitamente todas las variables de miembro asignadas en el montón de A;
  4. y finalmente el bloque de memoria que almacena dicha instancia de B se devuelve al montón; cuando se usó nuevo , primero asignó un bloque de memoria en el montón, luego invocó a los constructores para inicializarlo, ahora después de que se han invocado todos los destructores para finalizar el objeto el bloque donde residía el objeto se devuelve al montón.

El destructor de A se ejecutará cuando termine su tiempo de vida. Si desea liberar su memoria y ejecutar el destructor, debe eliminarlo si se asignó en el montón. Si se asignó en la stack, esto sucede automáticamente (es decir, cuando se sale del scope, vea RAII). Si es miembro de una clase (no un puntero, sino un miembro completo), esto sucederá cuando se destruya el objeto que lo contiene.

 class A { char *someHeapMemory; public: A() : someHeapMemory(new char[1000]) {} ~A() { delete[] someHeapMemory; } }; class B { A* APtr; public: B() : APtr(new A()) {} ~B() { delete APtr; } }; class C { A Amember; public: C() : Amember() {} ~C() {} // A is freed / destructed automatically. }; int main() { B* BPtr = new B(); delete BPtr; // Calls ~B() which calls ~A() C *CPtr = new C(); delete CPtr; B b; C c; } // b and c are freed/destructed automatically 

En el ejemplo anterior, cada eliminación y eliminación [] es necesaria. Y no se necesita eliminar (o de hecho se puede usar) donde no lo usé.

auto_ptr , unique_ptr y shared_ptr etc. son excelentes para hacer que esta gestión de por vida sea mucho más fácil:

 class A { shared_array someHeapMemory; public: A() : someHeapMemory(new char[1000]) {} ~A() { } // someHeapMemory is delete[]d automatically }; class B { shared_ptr APtr; public: B() : APtr(new A()) {} ~B() { } // APtr is deleted automatically }; int main() { shared_ptr BPtr = new B(); } // BPtr is deleted automatically 

Cuando llama a delete en un puntero asignado por nuevo, se llamará al destructor del objeto señalado.

 A * p = new A; delete p; // A:~A() called for you on obkect pointed to by p 

Se llama “destructor”, no “deconstructor”.

Dentro del destructor de cada clase, debe eliminar todas las demás variables miembro que hayan sido asignadas con nuevas.

editar: Para aclarar:

Digamos que tienes

 struct A {} class B { A *a; public: B () : a (new A) {} ~B() { delete a; } }; class C { A *a; public: C () : a (new A) {} }; int main () { delete new B; delete new C; } 

Asignar una instancia de B y luego eliminar está limpio, porque lo que B asigna internamente también se eliminará en el destructor.

Pero las instancias de clase C perderán memoria porque asigna una instancia de A que no libera (en este caso, C ni siquiera tiene un destructor).

Si tiene un puntero habitual ( A* ), no se llamará al destructor (y la memoria para la instancia A tampoco se liberará), a menos que lo delete explícitamente en el destructor de B Si desea destrucción automática, mire los punteros inteligentes como auto_ptr .

Deberías eliminar A ti mismo en el destructor de B.

 class B { public: B() { p = new int[1024]; } virtual ~B() { cout<<"B destructor"< 

Cuando tu lo hagas:

 B *pD = new D(); delete pD; 

Se llamará al destructor solo si su clase base tiene la palabra clave virtual.

Entonces, si no tiene un destructor virtual, solo se invocará ~ B (). Pero como tiene un destructor virtual, primero se llamará ~ D (), luego ~ B ().

Ningún miembro de B o D asignado en el montón será desasignado a menos que los elimine explícitamente. Y borrarlos llamará a su destructor también.

Me preguntaba por qué no se llamó al destructor de mi clase. La razón fue que olvidé incluir la definición de esa clase (#include “class.h”). Solo tuve una statement como “clase A”; y el comstackdor estaba contento con él y me dejó llamar “eliminar”.

No. el puntero será eliminado. Debería llamar a delete en A explicit en el destructor de B.

El destructor para el objeto de la clase A solo se invocará si se llama a la eliminación para ese objeto. Asegúrese de eliminar ese puntero en el destructor de clase B.

Para obtener un poco más de información sobre qué sucede cuando se invoca delete en un objeto, consulte: http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.9

no, no llamará a destructor para la clase A, debería llamarlo explícitamente (como dijo PoweRoy), eliminar la línea ‘eliminar ptr’; en el ejemplo para comparar …

  #include  class A { public: A(){}; ~A(); }; A::~A() { std::cout << "Destructor of A" << std::endl; } class B { public: B(){ptr = new A();}; ~B(); private: A* ptr; }; B::~B() { delete ptr; std::cout << "Destructor of B" << std::endl; } int main() { B* b = new B(); delete b; return 0; } 

Tienes algo como

 class B { A * a; } B * b = new B; b->a = new A; 

Si luego llama a delete b; , nada le sucede a a, y tienes una pérdida de memoria. Tratando de recordar delete b->a; no es una buena solución, pero hay un par de otros.

 B::~B() {delete a;} 

Este es un destructor para B que eliminará a. (Si a es 0, esa eliminación no hace nada. Si a no es 0, pero no apunta a la memoria de nuevo, obtienes corrupción de stack).

 auto_ptr a; ... b->a.reset(new A); 

De esta forma, no tendrá un puntero como, sino que un auto_ptr <> (shared_ptr <> también lo hará, u otros punteros inteligentes), y se eliminará automáticamente cuando b sea.

Cualquiera de estas formas funciona bien, y he usado ambas.