我的問題是關於初始化 c++類成員的.我見過許多這樣的**(包括在你的欄目中也見到過): csomeclass::csomeclass() 而在別的什麼地方則寫成下面的樣子: csomeclass::csomeclass() : x(0), y(1) 我的一些程式設計師朋友說第二種方法比較好,但他們都不知道為什麼是這樣.你能告訴我這兩種類成 員初始化方法的區別嗎?
回答 從技術上說,你的程式設計師朋友是對的,但是在大多數情況下,兩者實際上沒有區別.有兩個原因使 得我們選擇第二種語法,它被稱為成員初始化列表:乙個原因是必須的,另乙個只是出於效率考慮.
讓我們先看一下第乙個原因——必要性.設想你有乙個類成員,它本身是乙個類或者結構,而且只 有乙個帶乙個引數的建構函式.
class cmember };
因為 cmember 有乙個顯式宣告的建構函式,編譯器不產生乙個預設建構函式(不帶引數),所以 沒有乙個整數就無法建立 cmember 的乙個例項.
cmember* pm = new cmember; // error!! cmember* pm = new cmember(2); // ok
如果 cmember 是另乙個類的成員,你怎樣初始化它呢?你必須使用成員初始化列表.
class cmyclass ;
//必須使用成員初始化列表 cmyclass::cmyclass() : m_member(2) 沒有其它辦法將引數傳遞給 m_member, 如果成員是乙個常量物件或者引用也是一樣. 根據 c++ 的規則,常量物件和引用不能被賦值,它們只能被初始化. 第二個原因是出於效率考慮,當成員類具有乙個預設的建構函式和乙個賦值操作符時.mfc 的 cstring 提供了乙個完美的例子. 假定你有乙個類 cmyclass 具有乙個 cstring 型別的成員 m_str, 你想把它初始化為"yada yada.".
你有兩種選擇:
cmyclass::cmyclass()
//使用類成員列表 // and constructor cstring::cstring(lpctstr) cmyclass::cmyclass() : m_str(_t("yada yada"))
在它們之間有什麼不同嗎?
是的.編譯器總是確保所有成員物件在建構函式體執行之前初始化,因 此在第乙個例子中編譯的**將呼叫 cstring::cstring 來初始化 m_str,這在控制到達賦值語句 前完成.在第二個例子中編譯器產生乙個對 cstring:: cstring(lpctstr)的呼叫並將"yada yada"傳遞給這個函式. 結果是在第乙個例子中呼叫了兩個 cstring 函式 (建構函式和賦值操作符) , 而在第二個例子中只呼叫了乙個函式.在 cstring 的例子裡這是無所謂的,因為預設建構函式是內 聯的,cstring 只是在需要時為字串分配記憶體(即,當你實際賦值時).但是,一般而言,重複 的函式呼叫是浪費資源的,尤其是當建構函式和賦值操作符分配記憶體的時候.在一些大的類裡面, 你可能擁有乙個建構函式和乙個賦值操作符都要呼叫同乙個負責分配大量記憶體空間的 init 函式. 在 這種情況下,你必須使用初始化列表,以避免不要的分配兩次記憶體.在內部型別如 ints 或者 longs 或者其它沒有建構函式的型別下,在初始化列表和在建構函式體內賦值這兩種方法沒有效能上的差 別.不管用那一種方法,都只會有一次賦值發生.有些程式設計師說你應該總是用初始化列表以保持良 好習慣,但我從沒有發現根據需要在這兩種方法之間轉換有什麼困難.在程式設計風格上,我傾向於在 主體中使用賦值,因為有更多的空間用來格式化和新增注釋,你可以寫出這樣的語句:x=y=z=0; 或者 memset(this,0,sizeof(this)); 注意第二個片斷絕對是非物件導向的.
當我考慮初始化列表的問題時,有乙個奇怪的特性我應該警告你,它是關於 c++初始化類成員的, 它們是按照宣告的順序初始化的,而不是按照出現在初始化列表中的順序. class cmyclass ; cmyclass::cmyclass(int i) : m_y(i), m_x(m_y) 你可能以為上面的**將會首先做 m_y=i,然後做 m_x=m_y,最後它們有相同的值.但是編譯 器先初始化 m_x,然後是 m_y,,因為它們是按這樣的順序宣告的.結果是 m_x 將有乙個不可預 測的值.我的例子設計來說明這一點,然而這種 bug 會更加自然的出現.有兩種方法避免它,乙個 是總是按照你希望它們被初始化的順序宣告成員,第二個是,如果你決定使用初始化列表,總是按 照它們宣告的順序羅列這些成員.這將有助於消除混淆.
示例**片段,摘自live555:livemedia/media.hh
C 的初始化列表
class stu private string m stuname int m stuage 1.初始化列表先於建構函式執行。2.初始化列表只能用於建構函式。3.初始化列表可以同時初始化多個資料成員,效率高,速度快。注意 初始化列表中的成員變數的初始化順序只與成員變數在類中定義的順序有關,而與初始...
c 使用初始化列表來初始化字段
includeusing namespace std class student1 student1 int i b i a b 異常順序 發現a的值為0 b的值為2 說明初始化僅僅對b有效果,對a沒有起到初始化作用 student1 int a,int b a a b b 正常順序 發現a b 2...
C 中初始化列表的使用
1,初始化列表是在 c 中才引入的 2,以 類中是否可以定義 const 成員?這個問題來引入初始化列表 1,const 這個關鍵字可以定義真正意義上的常量,也可以在某些情況下定義唯讀變數 3,小實驗 1,下面的類定義是否合法?如果合法,ci 的值是什麼,儲存在 1 include 2 3class...