冒號運算符(「:」)在這個構造函數中做什麼?這相當於MyClass(m_classID = -1, m_userdata = 0);
嗎?C++構造函數名稱後面的冒號是做什麼的?
class MyClass {
public:
MyClass() : m_classID(-1), m_userdata(0) {
}
int m_classID;
void *m_userdata;
};
冒號運算符(「:」)在這個構造函數中做什麼?這相當於MyClass(m_classID = -1, m_userdata = 0);
嗎?C++構造函數名稱後面的冒號是做什麼的?
class MyClass {
public:
MyClass() : m_classID(-1), m_userdata(0) {
}
int m_classID;
void *m_userdata;
};
這是一個初始化列表,並且是構造函數的實現的一部分。
構造方法的簽名是:
MyClass();
這意味着構造函數可以不帶參數調用。這使得它成爲的默認構造函數,即,當您編寫MyClass someObject;
時將默認調用該構造函數。
該部分: m_classID(-1), m_userdata(0)
被稱爲初始化列表。這是一種用你選擇的值初始化你的對象的某些字段(如果你想要的話),而不是將它們保留爲未定義的。
執行初始化列表後,會執行構造函數體(在您的示例中恰好爲空)。在它裏面你可以做更多的任務,但是一旦你輸入了,所有的字段都已經被初始化 - 或者是隨機的,未指定的值,或者是你在初始化列表中選擇的值。這意味着您在構造函數體中執行的任務不會是初始化,而是值的更改。
它表示初始化列表的開始,它用於初始化對象的成員變量。
至於:MyClass(m_classID = -1, m_userdata = 0);
聲明一個構造函數,可以使用參數(這樣我就可以創建一個使用MyClass
MyClass m = MyClass(3, 4)
,這將導致m_classID
爲3,和m_userdata
爲4)。如果我沒有將參數傳遞給MyClass
構造函數,則會導致爲具有初始化列表的版本創建一個等效對象。
在這種情況下:是的,ist是等價的,因爲只涉及基本類型。
如果成員是類(結構),那麼你應該更喜歡初始化列表。這是因爲否則對象是默認構造,然後分配。
這是一個initialization list。在您的例子,它是相當像這樣(像這樣 - 並不意味着它在所有情況下的等價物):
class MyClass {
public:
MyClass(){
m_classID = -1;
m_userdata = 0;
}
int m_classID;
void *m_userdata;
};
它表示初始化程序列表的開始。
它也不等同於MyClass(m_classId = -1,m_userData = 0)。這試圖定義一個帶有2個參數的構造函數,這些參數具有默認值。然而,這些值缺乏類型,它不應該編譯。
這就是所謂的成員初始化列表。它用於調用超類的構造函數,並在創建時爲成員變量賦予初始值。
在這種情況下,它將m_classID
初始化爲-1,將m_userData
初始化爲NULL。
它不完全等同於在構造函數體中賦值,因爲後者首先創建成員變量,然後賦值給它們。通過初始化,初始值在創建時提供,因此在複雜對象的情況下,它可以更高效。
它不完全是一個操作符。它是構造函數的語法的一部分。
這是什麼意思,後面是一個成員變量列表和它們的初始值。
常量成員必須以這種方式進行初始化。非常量也可以在這裏初始化,只要它可以用單個表達式完成即可。如果需要比初始化成員更多的代碼,則必須將實際代碼放在{}之間。
很多人喜歡把他們所有的構造函數代碼放在initilizer列表中。我有一個經常用幾個初始化屏幕編寫類的同事,然後爲構造函數代碼添加「{}」。
它是在構造對象期間設置成員變量的初始化列表的開始。你的例子「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瞭解更多信息。
這是一個初始化列表。當你進入構造函數的主體時,所有的字段都已經被構造了;如果他們有默認的構造函數,那些已經被調用。現在,如果您在構造函數的主體中爲它們賦值,那麼您正在調用複製賦值運算符,這可能意味着釋放和重新獲取資源(如內存)(如果該對象有任何內容)。
所以在像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_;
};
如果你有一個引用成員,你*有*定義一個帶構造函數初始化列表的構造函數常常被誤認爲是錯誤的。但這並不完全正確。一個簡單的'MyClass m = {arg};'也可以正常工作。 – 2009-08-13 15:51:46
litb:但那麼你或多或少需要使用m = {arg};不是嗎?在我看來,能夠做MyClass m(ref)是相當期望的。 – Skurmedel 2009-08-13 16:02:40
@Skurmedel,我同意。但這並不意味着它是唯一的辦法,當然。 – 2009-08-13 17:00:43
它有時也用一絕成員初始化列表。如果您有一個作爲引用的成員變量,則必須使用成員初始化列表進行設置。 – Skurmedel 2009-08-13 15:33:44