现在的位置: 首页 > 综合 > 正文

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

2013年07月28日 ⁄ 综合 ⁄ 共 1109字 ⁄ 字号 评论关闭

先看如下程序

/*
	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很想,  貌似我不太懂, 就不说了

抱歉!评论已关闭.