C++对象被delete之后,其对象指针还能干些啥

  • 代码初觉

先看一段代码,想象它的结果是怎样的?

delete p;
p = NULL;
p->DoSomething();

这样的代码不会抛出异常或导致崩溃吗?对象都已经被delete掉而且都设为空了,怎么还可以调用其函数?

  • 诡异的非虚函数

但对C++而言,这样的代码是有可能调用成功且不会产生任何异常的。但有一个条件,那就是这个函数必须是非虚函数

示例代码如下:

class TestClass
{
public:
	void Go()
	{
		cout<<"Go OK!"<<endl;
	}
};

int main()
{
	TestClass* p = new TestClass();
	delete p;
	p = NULL;
	p->Go();

	return 0;
}
输出为:

原因:

该函数的调用地址在编译期间就已经确定,而且非虚函数的地址只跟类定义本身有关,与具体的实例对象无关,所以当对象的内存会销毁掉,并不会影响到对其非虚函数的调用。所以此次函数的调用可以成功。当然,如果该函数内部调用了对象的数据成员,还是会发生崩溃的。

  • 不好惹的虚函数

那再来看见虚函数,还会不会在delete之后被调用得到呢?

class TestClass
{
public:
	virtual void Go()
	{
		cout<<"Go OK!"<<endl;
	}
};

int main()
{
	TestClass* p = new TestClass();
	delete p;
	p = NULL;
	p->Go();

	return 0;
}

运行结果:崩溃

其原因就在于虚函数是延迟绑定的,不是在编译期间就确定下来地址的,而是跟对象息息相关的。C++的内存模型里就可以看出,虚函数是通过虚表指针来引用的,而虚表指针式在对象的前4个字节里面。那么当对象被销毁时,其虚表指针就被销毁,虚函数自然是无从引用了。

  • 引用成员变量,更是别想了

class TestClass
{
public:
	
	int m_data;
};

int main()
{
	TestClass* p = new TestClass();
	delete p;
	p = NULL;
	cout<<p->m_data; // crash!!!!

	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章