什麼時候用拷貝建構函式,和賦值建構函式:
(一)當用乙個已初始化過了的自定義類型別物件去初始化另乙個新構造的物件的時候,拷貝建構函式就會被自動呼叫。也就是說,當類的物件需要拷貝時,拷貝建構函式將會被呼叫。以下情況都會呼叫拷貝建構函式:
乙個物件以值傳遞的方式傳入函式體
乙個物件以值傳遞的方式從函式返回
乙個物件需要通過另外乙個物件進行初始化。
如果在類中沒有顯式地宣告乙個拷貝建構函式,那麼,編譯器將會自動生成乙個預設的拷貝建構函式,該建構函式完成物件之間的位拷貝。位拷貝又稱淺拷貝,後面將進行說明。
自定義拷貝建構函式是一種良好的程式設計風格,它可以阻止編譯器形成預設的拷貝建構函式,提高原始碼效率。
例子:
string a("hello");
string b("world");
string c = a; // 呼叫了拷貝建構函式,最好寫成 c(a);
c = b; // 呼叫了賦值建構函式。!
本例中第三個語句的風格較差,宜改寫成string c(a) 以區別於第四個語句。
(二)拷貝建構函式是在物件被建立時呼叫的,而賦值函式只能被已經存在了的物件呼叫。
不同點:
拷貝建構函式首先是乙個建構函式,它呼叫的時候產生乙個物件,是通過引數傳進來的那個物件來初始化,產生的物件。
operator=();是把乙個物件賦值給乙個原有的物件,所以如果原來的物件中有記憶體分配要先把記憶體釋放掉,而且還要檢查一下兩個物件是不是同乙個物件,如果是的話就不做任何操作。
還要注意的是拷貝建構函式是建構函式,不返回值;而賦值函式需要返回乙個物件自身的引用,以便賦值之後的操作。
淺拷貝和深拷貝
在某些狀況下,類內成員變數需要動態開闢堆記憶體,如果實行位拷貝,也就是把物件裡的值完全複製給另乙個物件,如a=b。這時,如果b中有乙個成員變數指標已經申請了記憶體,那a中的那個成員變數也指向同一塊記憶體。這就出現了問題:當b把記憶體釋放了(如:析構),這時a內的指標就是野指標了,出現執行錯誤。
深拷貝和淺拷貝的定義可以簡單理解成:如果乙個類擁有資源(堆,或者是其它系統資源),當這個類的物件發生複製過程的時候,這個過程就可以叫做深拷貝,反之物件存在資源,但複製過程並未複製資源的情況視為淺拷貝。
淺拷貝資源後在釋放資源的時候會產生資源歸屬不清的情況導致程式執行出錯。
下面是例子,注意看兩種函式怎麼寫,什麼地方用到:
#include using namespace std;
class ca
ca(const ca& other) //拷貝建構函式
ca & operator = (const ca& other) //賦值符過載
void show()
;//拷貝建構函式使用賦值運算子過載的**。
cexample::cexample(const cexample& rightsides)
//賦值操作符過載
cexample & cexample::operator = (const cexample& rightsides)
//其實也沒啥改進,但覺得這樣的寫法是不是更好?省了乙個temp臨時變數。
cexample & cexample::operator = (const cexample& rightsides)
拷貝建構函式和賦值建構函式
class cmystring 賦值建構函式 cmystring cmystring operator const cmystring str 新分配記憶體,將str的m pdata記憶體拷貝到m pdata中 m pdata new char strlen str.m pdata 1 strcpy...
拷貝建構函式和賦值建構函式
拷貝構造是確確實實構造乙個新的物件,並給新物件的私有成員賦上引數物件的私有成員的值,新構造的物件和引數物件位址是不一樣的,所以如果該類中有乙個私有成員是指向堆中某一塊記憶體,如果僅僅對該私有成員進行淺拷貝,那麼會出現多個指標指向堆中同一塊記憶體,這是會出現問題,如果那塊記憶體被釋放了,就會出現其他指...
拷貝建構函式和賦值構造
為什麼空類可以建立物件呢?複製建構函式的引數可以是 const 引用,也可以是非 const 引用。一般使用前者,這樣既能以常量物件 初始化後值不能改變的物件 作為引數,也能以非常量物件作為引數去初始化其他物件。乙個類中寫兩個複製建構函式,乙個的引數是 const 引用,另乙個的引數是非 const...