拷貝建構函式和賦值運算子

2021-06-20 11:31:17 字數 2175 閱讀 3510

把引數傳遞給函式有三種方法,一種是值傳遞,一種是傳位址,還有一種是傳引用。前者與後兩者不同的地方在於:當使用值傳遞的時候,會在函式裡面生成傳遞引數的乙個副本,這個副本的內容是按位從原始引數那裡複製過來的,兩者的內容是相同的。當原始引數是乙個類的物件時,它也會產生乙個物件的副本,不過在這裡要注意。一般物件產生時都會觸發建構函式的執行,但是在產生物件的副本時卻不會這樣,這時執行的是物件的複製建構函式。為什麼會這樣?嗯,一般的建構函式都是會完成一些成員屬性初始化的工作,在物件傳遞給某一函式之前,物件的一些屬性可能已經被改變了,如果在產生物件副本的時候再執行物件的建構函式,那麼這個物件的屬性又再恢復到原始狀態,這並不是我們想要的。所以在產生物件副本的時候,建構函式不會被執行,被執行的是乙個預設的建構函式(複製建構函式)。當函式執行完畢要返回的時候,物件副本會執行析構函式,如果你的析構函式是空的話,就不會發生什麼問題,但一般的析構函式都是要完成一些清理工作,如釋放指標所指向的記憶體空間。

這時候問題就可能要出現了。假如你在建構函式裡面為乙個指標變數分配了記憶體,在析構函式裡面釋放分配給這個指標所指向的記憶體空間,那麼在把物件傳遞給函式至函式結束返回這一過程會發生什麼事情呢?首先有乙個物件的副本產生了,這個副本也有乙個指標,它和原始物件的指標是指向同塊記憶體空間的。函式返回時,物件的析構函式被執行了,即釋放了物件副本裡面指標所指向的記憶體空間,但是這個記憶體空間對原始物件還是有用的,就程式本身而言,這是乙個嚴重的錯誤。然而錯誤還沒結束,當原始物件也被銷毀的時候,析構函式再次執行,對同一塊系統動態分配的記憶體空間釋放兩次是乙個未知的操作,將會產生嚴重的錯誤。

除了將物件傳遞給函式時會存在以上問題,還有一種情況也會存在以上問題,就是當函式返回物件時,會產生乙個臨時物件,這個臨時物件和物件的副本性質差不多。

解決問題的方法是什麼呢?首先我們想到的是不要以傳值的方式來傳遞引數,我們可以用傳位址或傳引用。沒錯,這樣的確可以避免上面的情況,而且在允許的情況下,傳位址或傳引用是最好的方法,但這並不適合所有的情況,有時我們不希望在函式裡面的一些操作會影響到函式外部的變數。那要怎麼辦呢?可以利用複製建構函式來解決這一問題。複製建構函式就是在產生物件副本的時候執行的,我們可以定義自己的複製建構函式。在複製建構函式裡面我們申請乙個新的記憶體空間來儲存建構函式裡面的那個指標所指向的內容。這樣在執行物件副本的析構函式時,釋放的就是副本裡由複製建構函式裡面所申請的那個記憶體空間。

複製建構函式:用乙個物件複製乙個新的物件時被呼叫,宣告為:類名(const 類名&物件名);

拷貝建構函式是一種特殊的建構函式,他由編譯器呼叫來完成一些基於同一類的其他物件的構造及初始化。它的唯一的乙個引數(物件的引用)是不可變的(因為是const型的)。這個函式經常用在函式呼叫期間於使用者定義型別的值傳遞及返回。拷貝建構函式要呼叫基類的拷貝建構函式和成員函式。在c++中,下面三種物件需要拷貝,因此,拷貝建構函式將會被呼叫。 

1).乙個物件以值傳遞的方式傳入函式體

2).乙個物件以值傳遞的方式從函式返回

3).乙個物件需要通過另外乙個物件進行初始化

如果在類中沒有顯式的宣告乙個拷貝建構函式,那麼,編譯器會私下裡為你制定乙個函式來進行物件之間的位拷貝(bitwise copy)。

複製建構函式與賦值操作符之間的區別

1.從概念上區分:

複製建構函式是建構函式,而賦值操作符屬於操作符過載範疇,它通常是類的成員函式

2.從原型上來區分:

複製建構函式原型classtype(const classtype &);無返回值

賦值操作符原型classtype& operator=(const classtype &);返回值為classtype的引用,便於連續賦值操作

3.從使用的場合來區分:

複製建構函式用於產生物件,它用於以下幾個地方:函式引數為類的值型別時、函式返回值為類型別時以及初始化語句,例如

classtype a; //

classtype b(a); //呼叫複製建構函式

classtype c = a; //呼叫複製建構函式

而賦值操作符要求『=』的左右物件均已存在,它的作用就是把『=』右邊的物件的值賦給左邊的物件

classtype e;

class type f;

f = e; //呼叫賦值操作符

拷貝建構函式和賦值運算子

來自 本文主要介紹了拷貝建構函式和賦值運算子的區別,以及在什麼時候呼叫拷貝建構函式 什麼情況下呼叫賦值運算子。最後,簡單的分析了下深拷貝和淺拷貝的問題。在預設情況下 使用者沒有定義,但是也沒有顯式的刪除 編譯器會自動的隱式生成乙個拷貝建構函式和賦值運算子。但使用者可以使用delete來指定不生成拷貝...

拷貝建構函式和賦值運算子區別

只有在賦值時,才呼叫賦值函式,當在宣告變數時,b b3 b1和b b4 b3 呼叫的函式是一樣的,均為拷貝建構函式。一 拷貝構造,是乙個的物件來初始化一邊記憶體區域,這邊記憶體區域就是你的新物件的記憶體區域賦值運算,對於乙個已經被初始化的物件來進行operator 操作 class a a a a ...

C 拷貝建構函式和賦值運算子

本文主要介紹了拷貝建構函式和賦值運算子的區別,以及在什麼時候呼叫拷貝建構函式 什麼情況下呼叫賦值運算子。最後,簡單的分析了下深拷貝和淺拷貝的問題。在預設情況下 使用者沒有定義,但是也沒有顯式的刪除 編譯器會自動的隱式生成乙個拷貝建構函式和賦值運算子。但使用者可以使用delete來指定不生成拷貝建構函...