c++构造函数和析构函数调用规则

来源:互联网 发布:java ioc原理 编辑:程序博客网 时间:2024/06/04 19:11

先看如下程序

/*coding by:ygqwanin 2013 / 08 / 20*/#include <iostream>#include <cstring>#include <algorithm>using namespace std;class Test{public:Test(int a):a(a){cout << "创建对象 : " << a << endl;}~Test(){cout << "销毁对象 : " << a << endl;}int a;};int main(){Test a(1);Test b(2);Test c(3);Test *d = new Test(4);Test *e = new Test(5);Test *f = new Test(6);cout << "--------------------" << endl;delete e;delete d;delete f;cout << "++++++++++++++++++++" << endl;return 0;}



运行结果如下:

创建对象 : 1
创建对象 : 2
创建对象 : 3
创建对象 : 4
创建对象 : 5
创建对象 : 6
--------------------
销毁对象 : 5
销毁对象 : 4
销毁对象 : 6
++++++++++++++++++++
销毁对象 : 3
销毁对象 : 2
销毁对象 : 1
请按任意键继续. . .





可以从运行结果看出, 用new运算符在堆上面开辟的空间跟delete的调用顺序有关

而直接在栈上面开辟的空间的调用规则却是固定的, 还是跟创建的顺序有关,为什么会这样呢?

看了下资料研究了下栈开辟空间的规则后发现是:

栈开辟空间:编译器生成代码在线程栈中移动指针开辟空间

栈销毁空间: 一样的道理, 只是这次移动的顺序是反着移动, 所以就跟生成空间的顺序相反, 那么结果就能够解释了



重点看看在堆上操作空间:

开辟: new一下的时候从全局堆中开辟了空间(这个开辟的算法我不清楚)然后赋值给栈内的指针d, 也就是说编译器一共开辟了两个空间, 空间一是在线程栈中生成一个指针, 空间二是在全剧堆中开辟一个对象空间; 并且栈空间中的指针指向堆空间的地址

销毁: 当delete d;的时候首先是销毁d指向的堆空间的地址里面的数据(怎么销毁的我也不知道), 然后没然后了

当d的作用于到了之后再由编译器自动销毁栈中的指针d;需要注意的是在销毁完d所指向的堆内空间时, d依然是指向那个堆空间的, 但是这个时候用d会出现错误的;

上面的这个错误是很严重的bug:

情况1: d 所指向的空间被系统收回去了, 这个时候d访问的是非法空间, 程序崩溃

情况2: d所指向的空间是别的对象的空间, 那么这个对d的后续操作有影响, 更不得了的是对那个堆内的数据可能照成破坏, 所以bug很严重的, 必须小心呀

情况3:跟2很想,  貌似我不太懂, 就不说了




原创粉丝点击