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

深拷貝與淺拷貝

技術標籤:C++c++指標

深拷貝與淺拷貝的區別

深拷貝和淺拷貝本質的區別在於淺拷貝獲取的是原物件的引用,深拷貝獲取的是原物件的複製實體

淺拷貝:簡單的賦值拷貝操作
深拷貝:在堆區重新申請空間,進行拷貝操作

為什麼要使用深拷貝

C++編譯器預設的拷貝建構函式都是淺拷貝。淺拷貝在類中存在指標的時候,拷貝的是原物件的引用,這會帶來一個問題:
在物件退出的時候,會呼叫解構函式對申請的堆記憶體進行釋放,如果是預設的淺拷貝,兩次解構函式會對同一個空間進行釋放,這會報錯。
為了避免淺拷貝的這個問題,必須使用深拷貝:拷貝建構函式重新申請一個記憶體空間,複製原物件。這樣釋放的時候就可以都釋放了。

例項

class Person {
public:
	Person():age(10)
	{
		cout << "person的無參建構函式" << endl;
	}

	Person(int a, int height) {
		age = a;
		m_height = new int(height);
		cout << "Person的有參建構函式" << endl;
	}
	//拷貝建構函式
	Person(const Person &p) {
		age = p.age;
		//深拷貝:重新申請一個堆,內容複製原物件
m_height = new int(*p.m_height); cout << "Person的拷貝建構函式" << endl; } //解構函式 ~Person() { cout << "person的解構函式" << endl; //對申請的堆進行釋放 if (m_height != NULL) { delete m_height; m_height = NULL; } } int age; int *m_height; }; //--------------深拷貝與淺拷貝----------------
void test1() { Person p1(16, 180); cout << "年齡為:" << p1.age << "\t身高為:" << *p1.m_height << "\t地址為:" << (int*)&p1.m_height << endl; Person p2(p1); cout << "年齡為:" << p2.age << "\t身高為:" << *p2.m_height << "\t地址為:" << (int*)&p2.m_height << endl; }

這裡的拷貝建構函式Person(const Person &p)需要我們自己定義成深拷貝形式(C++編譯器預設的是淺拷貝:m_height = p.m_height;)。

如果是淺拷貝,test1()在拷貝構造p2的時候,會直接把p2.m_height = p1.m_height,p1,p2指向了同一個堆的區域。在test1()結束後,會先呼叫p1的解構函式,把堆中的空間釋放掉;然後呼叫p2的解構函式,又想去釋放這個已經釋放的空間,這就會出錯。

這就需要改為深拷貝,new int(*p.m_height),重新在堆中申請一塊和原物件一模一樣的空間,這樣兩次解構函式就會分別去釋放p1,p2申請的空間,就不會出錯了。

在這裡插入圖片描述

可以看到結果,p1,p2申請的m_height的堆空間不同,就可以分別呼叫析構函數了。