C++ 类析构函数的显示调用和隐式调用

堆和栈

为了理解这个问题,我们必须首先弄明白“堆”和“栈”的概念。
堆区(heap) —— 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
栈区(stack)—— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
我们构造对象,往往都是在一段语句体中,比如函数,判断,循环,还有就直接被一对“{}”包含的语句体,这就是有时候为了使得类被析构掉,只使用一对{}来欺骗程序,使得析构函数被调用。这个对象在语句体中被创建,在语句体结束的时候被销毁。问题就在于,这样的对象在生命周期中是存在于栈上的。也就是说,如何管理,是系统完成而程序员不能控制的。所以,即使我们调用了析构,在对象生命周期结束后,系统仍然会再调用一次析构函数,将其在栈上销毁,实现真正的析构。总之,隐式调用析构函数的前提是类的创建是在栈上,而不是堆上。
所以,如果我们在析构函数中有清除堆数据的语句,调用两次意味着第二次会试图清理已经被清理过了的,根本不再存在的数据!这是件会导致运行时错误的问题,并且在编译的时候不会告诉你。

结论

1.显式调用的时候,析构函数相当于的一个普通的成员函数。
2.编译器隐式调用析构函数,如分配了对内存,显式调用析构的话引起重复释放堆内存的异常。
3.把一个对象看作占用了部分栈内存,占用了部分堆内存(如果申请了的话),这样便于理解这个问题。
4.系统隐式调用析构函数的时候,会加入释放栈内存的动作(而堆内存则由用户手工的释放)。
5.用户显式调用析构函数的时候,只是单纯执行析构函数内的语句,不会释放栈内存,摧毁对象。

系统在什么情况下不会自动调用析构函数呢?

如果对象被建立在堆上,系统就不会自动调用。一个常见的例子是new…delete组合。但是好在调用delete的时候,析构函数还是被自动调用了。很罕见的例外在于使用布局new的时候,在delete设置的缓存之前,需要显式调用的析构函数,这实在是很少见的情况。

举例

创建一个类指针
Pitch *thee3 = NULL;
创建函数的返回值是类指针,Pitch *thee = new Pitch(); thee就是函数的返回值,由于类指针在函数内用new来创建,说明thee是被创建在了堆上,thee3生命周期结束后,析构函数不被隐式调用,需要程序员自己释放,此时有2个方法可以解决:1.显示调用析构函数thee3->~Pitch(); 2.使用delete thee3;让delete函数去调用析构函数。

参考与致谢

本文参考且大部分拷贝于 http://blog.sina.com.cn/s/blog_bd60c3f4010188g5.html
在此向原文作者致谢~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值