1. 程式人生 > >類物件的淺拷貝和深拷貝(淺複製和深複製)

類物件的淺拷貝和深拷貝(淺複製和深複製)

淺拷貝(淺複製)

       在C++中經常隱式或顯式的出現物件的複製。當兩個物件之間進行復制時,若複製完成後,它們還共享某些資源(記憶體空間),其中一個物件的銷燬會影響另一物件,這種物件之間的複製稱為物件的淺拷貝。C++中採用賦值運算子進行物件複製是預設的是淺拷貝。

#include<iostream>
#include<string>
using namespace std;

class StudClass
{
	int Num;
	char *pName;
public:
	StudClass();//預設建構函式;
	StudClass(int n,char *p);//過載建構函式;
	~StudClass();//解構函式;
	void Display();
};

StudClass::StudClass(){}
StudClass::StudClass(int n,char *p)
{
	Num=n;
	pName=new char[10];
	strcpy(pName,p);
}
StudClass::~StudClass()
{
	delete [] pName;
}

void StudClass::Display()
{
	cout<<"學號:"<<Num<<"\t"<<"姓名:"<<pName<<endl;
}

void main()
{
	StudClass s(10,"Mary");
	StudClass t;
	t=s;         //物件的拷貝;
	s.Display();
	t.Display();
}
這個程式看上去是正確的,但執行時出現了錯誤。錯誤的原因在與物件的拷貝過程“t=s”,因為該語句執行的拷貝是淺拷貝,執行後,s和t物件的pName資料成員指向相同的記憶體空間,在main函式退出時,執行t的解構函式後,t.pName所指的空間被釋放,在執行s的解構函式時,pName所指向的記憶體已被釋放,就會出錯。


  

改正的方法是採用深拷貝。當兩個物件之間進行拷貝複製時,若複製完成後,他們不會共享任何資源(記憶體空間),其中一個物件的銷燬不會影響另一個物件,這種物件之間的拷貝稱為深拷貝(深複製)

改正上述程式的方法是採用過載運算子“=”實現深拷貝,在StudClass類中增加以下過載函式:

StudClass& operator=(StudClass& s)
	{
		pName=new char [10];
		Num=s.Num;
		strcpy(pName,s.pName);
		return *this;
	}

針對上述,程式碼還有兩點需要說明:

1、在賦值運算子(“=”)的過載函式中並未改變形參s的值,也不需要形參s實現值的雙向傳遞,形參為什麼要為引用型別?這是因為如果不採用引用型別,在呼叫該函式時,需要將實參拷貝到形參s中,而這種拷貝也是淺拷貝,淺拷貝不會為形參s的pName分配空間,導致形參和實參的pName指向同一塊記憶體空間。如果不採用引用的話,在賦值運算子的過載函式結束後pName所指的記憶體空間就被釋放,進而在實參呼叫解構函式時會出現錯誤。

2、在賦值運算子(“=”)的過載函式中,函式的返回值是StudClass&,物件引用型別。這裡為什麼要使返回值型別為引用型別呢?因為在執行“t=s;”時,相當於執行“t.operator=(s)”,如果賦值運算子過載函式的返回值不採用引用型別,還需將*this(即t)複製給返回物件,這中間就會產生淺拷貝,該返回物件和t物件的pName指向相同的空間,在呼叫兩次解構函式時會出錯。若用引用型別返回值,operator=(s)的返回物件和t物件就是同一個物件不會執行兩次解構函式。