建構函式、析構函式、賦值函式是每個類最基本的的函式。每個類只有乙個析構函式和乙個賦值函式。但是有很多建構函式(乙個為複製建構函式,其他為普通建構函式。對於乙個類a,如果不編寫上述四個函式,c++編譯器將自動為a產生四個預設的函式,即:
既然能自動生成函式,為什麼還需要自定義?原因之一是「預設的複製建構函式」和"預設的賦值函式「均採用」位拷貝「而非」值拷貝「
位拷貝 v.s. 值拷貝
為便於說明,以自定義string類為例,先定義類,而不去實現。
#include using namespace std;位拷貝拷貝的是位址,而值拷貝拷貝的是內容。class string
;
如果定義兩個string物件a, b。當利用位拷貝時,a=b,其中的a.val=b.val;但是a.m_data=b.m_data就錯了:a.m_data和b.m_data指向同乙個區域。這樣出現問題:
因此
當類中還有指標變數時,複製建構函式和賦值函式就隱含了錯誤。此時需要自己定義。
結論
注意
因此此時如果寫string s是錯誤的,因為定義了其他建構函式,就不會自動生成無參預設建構函式。
複製建構函式 v.s. 賦值函式
#include #include using namespace std;執行結果class string
;string::string(const char *str)
else
}string::string(const string &other)
string & string::operator=(const string &other)
else
}string::~string(void)
int main()
說明幾點
1. 賦值函式中,上來比較 this == &other 是很必要的,因為防止自複製,這是很危險的,因為下面有delete m_data,如果提前把m_data給釋放了,指標已成野指標,再賦值就錯了
2. 賦值函式中,接著要釋放掉m_data,否則就沒機會了(下邊又有新指向了)
3. 拷貝建構函式是物件被建立時呼叫,賦值函式只能被已經存在了的物件呼叫
注意:string a("hello"); string b("world"); 呼叫自定義建構函式
string c=a;呼叫拷貝建構函式,因為c一開始不存在,最好寫成string c(a);
為類新增賦值運算子函式:
型別定義
classcmystring要點:;
1、返回值型別為該型別的引用,並在函式結束前返回例項自身的引用(即 *this);
2、是否把傳入的引數宣告為常量引用【const cmystring &str】;
3、是否釋放自身已有記憶體,否則會造成「記憶體洩漏」;
4、是否判斷引數與當前示例是指向的同乙個物件;
解法:
/*適用於初級c++程式設計師的解法*/cmystring &cmystring::operator=(const cmystring &str) /*適用於高階c++程式設計師的解法 */cmystring &cmystring::operator=(const cmystring &str) //自動呼叫strtemp的析構函式,銷毀strtemp物件並**ptemp的記憶體 return *this; }
C 賦值建構函式 複製建構函式
編譯器提供乙個不接受任何引數,也不執行任何操作的建構函式,稱之為預設建構函式 這是因為創造物件的時候總會呼叫預設建構函式 klunk klunk 定義 klunk lunk 宣告 使用預設建構函式 如果定義了建構函式,c 不會定義預設建構函式,如果希望建立物件時不顯示地對他進行初始化,則必須顯示的定...
複製建構函式 與 賦值函式 的區別
建構函式 析構函式 賦值函式是每個類最基本的的函式。每個類只有乙個析構函式和乙個賦值函式。但是有很多建構函式 乙個為複製建構函式,其他為普通建構函式。對於乙個類a,如果不編寫上述四個函式,c 編譯器將自動為a產生四個預設的函式,即 既然能自動生成函式,為什麼還需要自定義?原因之一是 預設的複製建構函...
複製建構函式 與 賦值函式 的區別
建構函式 析構函式 賦值函式是每個類最基本的的函式。每個類只有乙個析構函式和乙個賦值函式。但是有很多建構函式 乙個為複製建構函式,其他為普通建構函式。對於乙個類a,如果不編寫上述四個函式,c 編譯器將自動為a產生四個預設的函式,即 既然能自動生成函式,為什麼還需要自定義?原因之一是 預設的複製建構函...