1. 程式人生 > 其它 >C++深淺拷貝

C++深淺拷貝

技術標籤:基礎學習c++

淺拷貝:簡單的賦值拷貝操作。當指標進行淺拷貝時可能會導致多個物件共用同一記憶體資源,同一塊記憶體資源釋放多次,導致崩潰或者記憶體洩漏,
深拷貝:在堆區中重新申請空間,進行拷貝操作。

例證:

#include<iostream>
using namespace std;
class Person
{
public:
	int age;
	int* height;
	Person()//無參建構函式
	{
		age = 19;
		height = new int(169);
	}
	~Person()//解構函式,其作用可以用來釋放堆區的資料
	{
		if
(height != NULL) { delete height; height = NULL; } } }; int main() { Person p; Person q(p); system("pause"); }

程式執行會出錯
編譯器會提供一個預設的拷貝建構函式:

	Person(const Person &p)
	{
		age = p.age;
		height = p.height;
	}

“height = p.height;”這一句為簡單的賦值操作,進行了淺拷貝,因此q的height指標與p的height指標會指向同一個記憶體空間,在程式結束前需要呼叫各自的解構函式,由於棧的特點,先呼叫q的析構,它的height指標不為空,因此會釋放它所指向的空間,再呼叫p的解構函式,這裡出現了問題,由於p的height指標不為空(其實是野指標了),因此需要釋放其所指的記憶體空間,此空間在q的解構函式中已經被釋放了,再次釋放未非法操作,因此程式出錯。

要解決此等錯誤,就要使得兩指標指向不同的記憶體,因此需要我們自己提供拷貝建構函式:

	Person(const Person &p)//拷貝建構函式
	{
		age = p.age;
		height = new int(*p.height);
	}

這樣p和q的指標都指向堆中不同記憶體單元,程式執行無誤。
在寫程式時,儘量避免多個指標指向同一個記憶體單元。

補:
預設情況下,編譯器會給一個類提供三個函式:無參建構函式(函式體為空)、解構函式(函式體為空)、拷貝建構函式(對各屬性進行值拷貝)
如果程式設計師提供了有參建構函式,則編譯器不再提供無參建構函式,但會提供解構函式和拷貝建構函式。

如果程式設計師只提供了拷貝建構函式,則編譯器不再提供任何其他建構函式。