C++ 析构函数


  堆区(heap —— 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
    栈区(stack—— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。如果对象被建立在堆上,系统就不会自动调用。
    
所以,如果我们在析构函数中有清除堆数据的语句,调用两次意味着第二次会试图清理已经被清理过了的,根本不再存在的数据!这是件会导致运行时错误的问题,并且在编译的时候不会告诉你!

 

调用析构函数:

  撤销类对象时会自动调用析构函数,如变量超出作用域时会自动撤销。动态分配的对象只有在指向该对象的指针被删除时才撤销,如果没有删除指向动态对象的指针,则不会运行该对象的析构函数,对象就一直存在,导致内存泄漏,而且,对象内部使用的任何资源也不会释放。

  显式的调用析构函数是一件非常危险的事情,,我们自己所谓的显式调用析构函数,实际上只是调用了一个成员函数,并没有真正意义上的让对象析构。  

1 Fred *p=new Fred();
2 delete p;//自动调用p->~Fred

  但是如果我们将上一条语句改为:p->~Fred();呢。会出现什么情况呢?因为显示调用析构函数不会释放Fred对象本身的内存,也就是栈内存,所以不要这么做,记住delete做了2件事情:调用析构函数和回收内存

  编译器隐式调用析构函数,如分配了堆内存,显式调用析构的话引起重复释放堆内存的异常。把一个对象看作占用了部分栈内存,占用了部分堆内存(如果申请了的话),这样便于理解这个问题(显示调用的时候,系统还是会自动执行一遍,那么总共释放了两次heap数据,释放了一次stack数据)
   
 系统隐式调用析构函数的时候,会加入释放栈内存的动作(而堆内存则由用户手工的释放)
   
 用户显式调用析构函数的时候,只是单纯执行析构函数内的语句,不会释放栈内存,摧毁对象

复制代码
 1 class aaa
 2 {
 3 public:
 4     aaa(){p = new char[1024];}
 5     ~aaa(){cout<<"deconstructor"<<endl; delete []p; p=NULL;}
 6     void disp(){cout<<"disp"<<endl;}
 7 private:
 8     char *p;
 9 };
10 void main()
11 {
12 aaa a;
13 a.~aaa();
14 a.disp();
15 } 
复制代码

  这样的话,第一次显式调用析构函数,相当于调用一个普通成员函数,执行函数语句,释放了堆内存,但是并未释放栈内存,对象还存在(但已残缺,存在不安全因素);
第二次调用析构函数,再次释放堆内存(此时报异常),然后释放栈内存,对象销毁

  撤销一个容器(不管是标准库容器还是内置数组),会运行容器中的类类型元素的析构函数。注意容器中的元素总是逆序撤销的,先撤销下标为size()-1的元素……最后撤销下标为0的元素

 

编写显示析构函数

  许多类不需要显式析构函数,尤其具有构造函数的类不一定需要定义自己的析构函数。仅在有些工作需要析构函数完成时,才需要析构函数(显式的)。析构函数并不仅限于用来释放资源,一般而言,析构函数可以执行任意操作,该操作是类设计者希望该类对象在使用完毕后执行的。

  三法则(rule of three):如果类需要析构函数,那么它也需要赋值操作符和复制构造函数,即需要析构函数,则需要这三个复制控制成员

  析构函数是一个成员函数,在类名前加一个代字号(~),它没有返回值,没有形参。因为不能指定形参,所以不能重载析构函数。所以只能为一个类提供一个析构函数。

 

合成析构函数:

  与其他两个复制控制函数不同,编译器总是会合成一个析构函数(不论我们是否显示定义了一个析构函数),合成析构函数创建时逆序地撤销每一个非static成员(stack上面的成员)。析构函数和其他两个复制控制函数最大的不同是:即使我们编写了自己的析构函数,合成析构函数仍然运行


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值