删除调用析构函数吗?
我有一个类(A)使用堆内存分配的一个领域。 类A被实例化并作为指针字段存储在另一个类(B)中。
当我完成对象B,我打电话给删除,我假设调用析构函数…但是这是否也调用类A中的析构函数?
编辑:
从答案中,我认为(如果不正确,请编辑):
-
delete
B实例B调用B ::〜B(); - 它调用
A::~A();
-
and A::~A
应该明确地delete
and A::~A
所有堆分配成员variables。 - 最后将存储所述B实例的内存块返回给堆 – 当使用new时,它首先在堆上分配一块内存,然后调用构造函数对其进行初始化,现在在调用所有析构函数完成对象对象所在的块返回到堆中。
A的析构函数将在其生命周期结束时运行。 如果你想让它的内存被释放并且析构函数运行,你必须在堆中分配它。 如果它被分配在堆栈上,则会自动发生(即当它超出范围时,请参阅RAII)。 如果它是一个类的成员(不是一个指针,而是一个完整的成员),那么当包含的对象被销毁时会发生这种情况。
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
在上面的例子中,每个删除和删除[]是必要的。 并没有需要删除(或确实能够使用),我没有使用它。
auto_ptr
, unique_ptr
和shared_ptr
等等都非常适合让这个终身pipe理变得更容易:
class A { shared_array<char> someHeapMemory; public: A() : someHeapMemory(new char[1000]) {} ~A() { } // someHeapMemory is delete[]d automatically }; class B { shared_ptr<A> APtr; public: B() : APtr(new A()) {} ~B() { } // APtr is deleted automatically }; int main() { shared_ptr<B> BPtr = new B(); } // BPtr is deleted automatically
当你调用由new分配的指针的delete时,指向的对象的析构函数将被调用。
A * p = new A; delete p; // A:~A() called for you on obkect pointed to by p
它被命名为“析构函数”,而不是“解构函数”。
在每个类的析构函数内部,你必须删除所有已经用new分配的成员variables。
编辑:澄清:
说你有
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; }
分配一个B的实例然后删除是干净的,因为B在内部分配的内容也将在析构函数中被删除。
但是类C的实例会泄漏内存,因为它分配了一个它不会释放的实例(在这种情况下,C甚至没有析构函数)。
如果你有一个通常的指针( A*
),那么析构函数将不会被调用(而内存中的A
实例也不会被释放),除非你在B
的析构函数中明确地delete
。 如果你想自动销毁看像智能指针像auto_ptr
。
您应该在B的析构函数中删除A
class B { public: B() { p = new int[1024]; } virtual ~B() { cout<<"B destructor"<<endl; //p will not be deleted EVER unless you do it manually. } int *p; }; class D : public B { public: virtual ~D() { cout<<"D destructor"<<endl; } };
当你这样做时:
B *pD = new D(); delete pD;
仅当您的基类具有virtual关键字时才会调用析构函数。
那么如果你没有一个虚拟的析构函数,那么只会调用〜B()。 但是因为你有一个虚拟析构函数,所以首先调用D(),然后调用〜B()。
除非您明确地删除它们,否则堆中分配的B或D成员将不会被释放。 删除它们也会调用它们的析构函数。
我想知道为什么我的类的析构函数没有被调用。 原因是我忘了包含该类的定义(#include“class.h”)。 我只有一个像“A级”的声明 编译器很高兴,让我称之为“删除”。
不,指针将被删除。 你应该在B的析构函数中明确地调用A的删除。
类A的对象的析构函数只有在调用该对象的delete时才被调用。 确保在类B的析构函数中删除该指针
有关在对象上调用delete时会发生什么的更多信息,请参见: http : //www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.9
不,它不会调用类A的析构函数,你应该明确地调用它(像PoweRoy告诉),删除行'删除ptr;' 在例子比较…
#include <iostream> 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; }
你有类似的东西
class B { A * a; } B * b = new B; b->a = new A;
如果你再叫delete b;
,没有任何事情发生,你有一个内存泄漏。 试着记住delete b->a;
不是一个好的解决scheme,但也有一些其他的。
B::~B() {delete a;}
这是B的一个析构函数,它将删除一个。 (如果a是0,那么这个删除就不会执行任何操作。如果a不是0,但是不指向新的内存,那么会导致堆损坏。)
auto_ptr<A> a; ... b->a.reset(new A);
这样你就没有一个指针,而是一个auto_ptr <>(shared_ptr <>也可以,或者其他的智能指针),当b是时,它会被自动删除。
这两种方法都行得通,而且我都用过。