先看如下程序
/* coding by:ygqwan in 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很想, 貌似我不太懂, 就不说了