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;
}


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