拷貝建構函式 賦值運算子 建構函式的區別及關係?

2021-07-25 22:13:15 字數 1189 閱讀 9646

1、為什麼要有拷貝建構函式,它跟建構函式有什麼區別?

答:拷貝建構函式其實也是建構函式,只不過它的引數是const的類自身的物件的引用。如果類裡面沒有指標成員(該指標成員指向動態申請的空間),是沒有必要編寫拷貝建構函式的。我們知道,如果有乙個類cobj,它已經產生了乙個物件obja,現在又用cobj去建立objb,如果程式中使用語句objb = obja;也就是說直接使用obja的資料給objb賦值。這對於一般的類,沒有任何問題,但是如果cobj裡面有個char* pstr的成員,用來存放動態申請的字串的位址,在obja中使用new方法動態申請了記憶體並讓obja.pstr指向該申請的空間,在ojbb = ojba之後,obja.pstr和objb.pstr將同時指向那片空間,這樣到導致了誰也不知道到底該由誰來負責釋放那塊空間,很有可能導致同一塊記憶體被釋放兩次。使用拷貝建構函式,先申請obja.pstr所指向的空間大小的空間,然後將空間內容拷貝過來,這樣就不會同時指向同一塊記憶體,各自有各自申請的記憶體,各自負責釋放各自申請的記憶體,從而解決了剛才的問題。所以這裡的「拷貝」拷貝的是動態申請的空間的內容,而不是類本身的資料。另外注意到,拷貝建構函式的引數是物件的引用,而不是物件的指標。至於為什麼要用引用,不能夠用指標暫時還沒有搞明白,等搞明白了再說。

2、為什麼要對=賦值操作符進行過載?

答:接上面的例子,使用者在使用語句objb = obja的時候,或許objb的pstr已經指向了動態申請的空間,如果直接簡單將其指向的位址覆蓋,就會導致記憶體洩露,所以需要對=賦值操作符進行過載,在過載函式中判斷pstr如果已經指向了動態申請的空間,就先將其釋放。

3、拷貝建構函式和賦值操作符過載(=)的關係。

答:從原文的例子中可以看出,=賦值操作符過載比拷貝建構函式做得要多,它除了完成拷貝建構函式所完成的拷貝動態申請的記憶體的資料之外,還釋放了原本自己申請的記憶體空間。所以原文最後給出的拷貝建構函式的實現可以使用=賦值操作符的過載來完成。

4、拷貝建構函式何時被呼叫?

a.物件的直接賦值也會呼叫拷貝建構函式,即乙個物件需要通過另外乙個物件進行初始化,(既然有了=賦值操作符過載,為什麼還要呼叫拷貝建構函式?);

b.函式引數傳遞只要是按值傳遞也呼叫拷貝建構函式-¬—即乙個物件以值傳遞的方式傳入函式體

c.函式返回只要是按值返回也呼叫拷貝建構函式—-即乙個物件以值傳遞的方式從函式體返回。

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

把引數傳遞給函式有三種方法,一種是值傳遞,一種是傳位址,還有一種是傳引用。前者與後兩者不同的地方在於 當使用值傳遞的時候,會在函式裡面生成傳遞引數的乙個副本,這個副本的內容是按位從原始引數那裡複製過來的,兩者的內容是相同的。當原始引數是乙個類的物件時,它也會產生乙個物件的副本,不過在這裡要注意。一般...

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

物件的 生命週期 管理意味著完全地控制物件的誕生 繁殖和消亡的過程。使用拷貝建構函式和賦值運算子,可以更快的進行物件的繁殖操作。拷貝建構函式是一種建構函式,其原型類似於 classname const classname x 賦值建構函式的作用就是建立乙個物件,該物件是同乙個類中已有物件的精確副本。...

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

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