析构函数和构造函数的功能恰恰相反,也就是说,析构函数是完成对分配内存资源的回收!下面我们分两种情况来讨论:
(1)非显式的调用析构函数(2)显式的调用析构函数
一.非显式的调用析构函数
(1)当类中不含有在堆中分配的内存时,系统在对象消失后会自动的调用该对象的析构函数
(2)当类中含有new/malloc等在堆中分类的内存的时候,我们必须用delete/free释放掉分配的内存,析构函数才会被调用,如果没有delete,那么就会造成内存泄漏。举例说明:
//test C++destructor #include <iostream> using namespace std; class A { public: A () { cout<<"constructor implement"<<endl; } ~A() { cout<<"destructor implement"<<endl; } private: int m_a; }; void main() { A *a1 = new A(); //在堆中分配内存 A a2;//在栈上分配内存 delete a1; }
执行结果:
二.显式的调用析构函数
许多类不需要显式析构函数,尤其是具有构造函数的类不一定需要定义自己的析构函数,仅仅在有些工作需要析构函数完成时,才需要析构函数。在这里,我们先不讲很多,具体的可以参见博客:
http://www.cppblog.com/lf426/archive/2008/04/12/46909.html
http://www.cnblogs.com/fangyukuan/archive/2010/08/28/1811119.html
下面再说一下在多重继承中基类中为什么要把析构函数加上virtual关键字。看下面的代码:
//test C++destructor #include <iostream> using namespace std; class A { public: A () { cout<<"A constructor implement"<<endl; pa = new int; } ~A() { cout<<"A destructor implement"<<endl; } private: int m_a; int *pa; }; class B: public A { public: B() { cout<<"B constructor"<<endl; pb = new int; } ~B() { cout<<"B destructor"<<endl; } private: int m_b; int *pb; }; void main() { // A *a1 = new A(); // A a2; // delete a1; A *b = new B; delete b; }
运行结果为:
可以发现,只有基类的析构函数被调用,派生类没有被调用,这势必发生内存泄漏。因此需要在基类的析构函数前面加上virtual,这样的目的是发生动态绑定,当delete b时,首先能调用派生类的析构函数。