類物件的淺拷貝和深拷貝(淺複製和深複製)
阿新 • • 發佈:2019-02-11
淺拷貝(淺複製)
在C++中經常隱式或顯式的出現物件的複製。當兩個物件之間進行復制時,若複製完成後,它們還共享某些資源(記憶體空間),其中一個物件的銷燬會影響另一物件,這種物件之間的複製稱為物件的淺拷貝。C++中採用賦值運算子進行物件複製是預設的是淺拷貝。
這個程式看上去是正確的,但執行時出現了錯誤。錯誤的原因在與物件的拷貝過程“t=s”,因為該語句執行的拷貝是淺拷貝,執行後,s和t物件的pName資料成員指向相同的記憶體空間,在main函式退出時,執行t的解構函式後,t.pName所指的空間被釋放,在執行s的解構函式時,pName所指向的記憶體已被釋放,就會出錯。#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(); }
改正的方法是採用深拷貝。當兩個物件之間進行拷貝複製時,若複製完成後,他們不會共享任何資源(記憶體空間),其中一個物件的銷燬不會影響另一個物件,這種物件之間的拷貝稱為深拷貝(深複製)。
改正上述程式的方法是採用過載運算子“=”實現深拷貝,在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物件就是同一個物件不會執行兩次解構函式。