1. 程式人生 > >建構函式,拷貝構造和賦值運算子‘=‘的區別

建構函式,拷貝構造和賦值運算子‘=‘的區別

例子

class CExample  

{

private: 

  char *pBuffer;   //類的物件中包含指標,指向動態分配的記憶體資源 

  int nSize; 

public:  

  CExample()   {pBuffer=NULL;nSize=0;}

  ~CExample()  {delete pBuffer;}  

  void Init(int n)  { pBuffer=new char[n]; nSize=n;}

};   

int main( )  

 {   

CExample theObjone;           //物件建立呼叫建構函式

theObjone.Init(40);    

CExample theObjtwo=theObjone; //物件複製(因初始化),呼叫拷貝建構函式

        (有指標成員,使用預設拷貝構造有缺點(僅複製指標),故要用自定義的)

CExample theObjthree;  

theObjthree.Init(60);   

theObjthree=theObjone;        //物件賦值操作(因非初始化),呼叫賦值運算子

         (有指標成員,使用默賦值符“=”有缺點(舊指標被丟棄),故要過載運算子)

}

注意:"="號的兩種不同使用,初始化和賦值

第三行也用到了"="號,該"="在物件宣告語句中,表示初始化。更多時候,這種初始化也可用括號()表示。而最後一行的"="號是賦值符,使用預設賦值符"=",是把被賦值物件的原內容被清除,並用右邊物件的內容填充。

 

建構函式  主要用來在建立物件時, 即為物件成員變數賦初始值 

 

拷貝建構函式 形式為X(X&),用來完成基於同一類的其他物件的構建及初始化

一個物件需要通過另外一個物件進行初始化,呼叫拷貝建構函式。

初始化和賦值的不同含義是建構函式呼叫的原因。事實上,拷貝建構函式是由普通建構函式和賦值操作符共同實現的

 

預設拷貝建構函式(淺拷貝)

CExample theObjtwo=theObjone;"用theObjone初始化theObjtwo。

呼叫預設拷貝構造含,  其完成方式是記憶體拷貝(淺拷貝),複製所有成員的值。

完成後,theObjtwo.pBuffer==theObjone.pBuffer。   即它們將指向同樣的地方,指標雖然複製了,但所指向的空間並沒有複製,而是由兩個物件共用了。

這樣不符合要求,物件之間不獨立了,併為空間的刪除帶來隱患(產生野指標

 

自定義拷貝建構函式(深拷貝)

因此可以在建構函式中新增操作來解決指標成員的問題,即自定義的拷貝建構函式   

//自定義拷貝建構函式
CExample::CExample(const CExample& RightSides)    
{   
 nSize=RightSides.nSize;  //複製常規成員 
 pBuffer=new char[nSize]; //複製指標指向的內容   
 memcpy(pBuffer,RightSides.pBuffer,nSize*sizeof(char));   
}

 

這樣,定義新物件,並用已有物件初始化新物件時,CExample(const CExample& RightSides)將被呼叫,而已有物件用別名RightSides傳給建構函式,以用來作複製。    

原則上,應該為所有包含動態分配成員的類都提供自定義的拷貝建構函式。

注意:記憶體拷貝函式void *memcpy(void *dest, constvoid *src, size_t n)

 

預設賦值操作符"="

//賦值操作符過載  
CExample & CExample::operator = (const CExample& RightSides)   
{   
 nSize=RightSides.nSize;      //複製常規成員   
 char *temp=new char[nSize];//複製指標指向的內容(預設=的缺點)   
 memcpy(temp,RightSides.pBuffer,nSize*sizeof(char));   
 delete []pBuffer;    //刪除原指標指向內容(避免記憶體洩露)
          
 pBuffer=NULL;     //同時把原指標置為NULL(避免野指標)
 pBuffer=temp;      //建立新指向  
 return *this ;
}  

"="的預設(預設)操作只是將成員變數的值相應複製,舊的值被自然丟棄    

最後一行的"="表示賦值操作,將物件theObjone的內容複製到物件theObjthree,這其中涉及到物件theObjthree原有內容的丟棄,新內容的複製。   

由於物件內包含指標,將造成不良後果:指標的值被丟棄了,但指標指向的內容並未釋放(導致記憶體洩露)。指標的值被複制了,但指標所指內容並未複製(導致新指標指的內容丟了

即產生兩方面的問題:丟棄舊指標(導致記憶體洩露),僅複製新指標(導致內容丟了)

因此,包含動態分配成員的類除了提供拷貝建構函式外,還應該考慮過載"="賦值操作符號

 

 

過載"="賦值操作符

--------------------- 本文來自 日月行者 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/qq_16445683/article/details/46043505?utm_source=copy