2009-08-13 852 views

回答

79

這是一個初始化列表,並且是構造函數的實現的一部分。

構造方法的簽名是:

MyClass(); 

這意味着構造函數可以不帶參數調用。這使得它成爲的默認構造函數,即,當您編寫MyClass someObject;時將默認調用該構造函數。

該部分: m_classID(-1), m_userdata(0)被稱爲初始化列表。這是一種用你選擇的值初始化你的對象的某些字段(如果你想要的話),而不是將它們保留爲未定義的。

執行初始化列表後,會執行構造函數體(在您的示例中恰好爲空)。在它裏面你可以做更多的任務,但是一旦你輸入了,所有的字段都已經被初始化 - 或者是隨機的,未指定的值,或者是你在初始化列表中選擇的值。這意味着您在構造函數體中執行的任務不會是初始化,而是值的更改。

2

它表示初始化列表的開始,它用於初始化對象的成員變量。

至於:MyClass(m_classID = -1, m_userdata = 0);

聲明一個構造函數,可以使用參數(這樣我就可以創建一個使用MyClassMyClass m = MyClass(3, 4),這將導致m_classID爲3,和m_userdata爲4)。如果我沒有將參數傳遞給MyClass構造函數,則會導致爲具有初始化列表的版本創建一個等效對象。

0

在這種情況下:是的,ist是等價的,因爲只涉及基本類型。

如果成員是類(結構),那麼你應該更喜歡初始化列表。這是因爲否則對象是默認構造,然後分配。

1

這是一個initialization list。在您的例子,它是相當像這樣(像這樣 - 並不意味着它在所有情況下的等價物):


class MyClass { 

public: 

    MyClass(){ 
     m_classID = -1; 
     m_userdata = 0; 
    } 

    int m_classID; 
    void *m_userdata; 

};
2

它表示初始化程序列表的開始。

它也不等同於MyClass(m_classId = -1,m_userData = 0)。這試圖定義一個帶有2個參數的構造函數,這些參數具有默認值。然而,這些值缺乏類型,它不應該編譯。

1

這就是所謂的成員初始化列表。它用於調用超類的構造函數,並在創建時爲成員變量賦予初始值。

在這種情況下,它將m_classID初始化爲-1,將m_userData初始化爲NULL。

它不完全等同於在構造函數體中賦值,因爲後者首先創建成員變量,然後賦值給它們。通過初始化,初始值在創建時提供,因此在複雜對象的情況下,它可以更高效。

+1

它有時也用一絕成員初始化列表。如果您有一個作爲引用的成員變量,則必須使用成員初始化列表進行設置。 – Skurmedel 2009-08-13 15:33:44

1

它不完全是一個操作符。它是構造函數的語法的一部分。

這是什麼意思,後面是一個成員變量列表和它們的初始值。

常量成員必須以這種方式進行初始化。非常量也可以在這裏初始化,只要它可以用單個表達式完成即可。如果需要比初始化成員更多的代碼,則必須將實際代碼放在{}之間。

很多人喜歡把他們所有的構造函數代碼放在initilizer列表中。我有一個經常用幾個初始化屏幕編寫類的同事,然後爲構造函數代碼添加「{}」。

1

它是在構造對象期間設置成員變量的初始化列表的開始。你的例子「MyClass(m_classID = -1,m_userdata = 0);」是不可能的,因爲你還沒有定義正確的構造函數,你將無法訪問成員變量參數列表反正...你可以有這樣的:

MyClass(int classId = -1, void* userData = 0) : m_classID(classId), m_userdata(userData) {} 

的初始化器列表被認爲是優於:

MyClass(int classId = -1, void* userData = 0) { 
    m_classID = classId; 
    m_userdata = userData; 
} 

Google瞭解更多信息。

37

這是一個初始化列表。當你進入構造函數的主體時,所有的字段都已經被構造了;如果他們有默認的構造函數,那些已經被調用。現在,如果您在構造函數的主體中爲它們賦值,那麼您正在調用複製賦值運算符,這可能意味着釋放和重新獲取資源(如內存)(如果該對象有任何內容)。

所以在像int這樣的基本類型的情況下,與在構造函數體中分配它們相比,沒有什麼優勢。在具有構造函數的對象的情況下,它是一種性能優化,因爲它避免了經歷兩個對象初始化而不是一個。

如果其中一個字段是引用,則需要初始化列表,因爲引用永遠不能爲空,即使在對象構造和構造函數體之間的短暫時間內也是如此。下面會引發錯誤C2758:「MyClass的:: member_」:必須在構造函數基/成員初始化列表初始化

class MyClass { 
public : 
    MyClass(std::string& arg) { 
     member_ = arg; 
    } 
    std::string& member_; 
}; 

的唯一正確的方法是:

class MyClass { 
public : 
    MyClass(std::string& arg) 
     : member_(arg) 
    { 
    } 
    std::string& member_; 
}; 
+2

如果你有一個引用成員,你*有*定義一個帶構造函數初始化列表的構造函數常常被誤認爲是錯誤的。但這並不完全正確。一個簡單的'MyClass m = {arg};'也可以正常工作。 – 2009-08-13 15:51:46

+0

litb:但那麼你或多或少需要使用m = {arg};不是嗎?在我看來,能夠做MyClass m(ref)是相當期望的。 – Skurmedel 2009-08-13 16:02:40

+0

@Skurmedel,我同意。但這並不意味着它是唯一的辦法,當然。 – 2009-08-13 17:00:43