論壇中回答一個別人問題
C++ Primer中在講構造函數初始化列表的時候有這么一段話:
無論是在構造函數初始化列表中初始化成員,還是在構造函數體中對它們賦值,最終結果是相同的。不同之處在于,使用構造函數初始化列表的版本初始化數據成員,沒有定義初始化列表的構造函數版本在構造函數體中對數據成員賦值。
請問這里的初始化數據成員與對數據成員賦值的含義是什么?有什么區別?
我知道在數據成員有默認構造函數時是有不同的,但對其他類型的成員呢?其他類型成員的初始化和賦值有區別嗎?
=========================================================================
是這個意思:
首先把數據成員按類型分類
1。內置數據類型,復合類型(指針,引用)
2。用戶定義類型(類類型)
分情況說明:
對于類型1,在成員初始化列表和構造函數體內進行,在性能和結果上都是一樣的
對于類型2,結果上相同,但是性能上存在很大的差別
因為類類型的數據成員對象在進入函數體是已經構造完成,也就是說在成員初始化列表處進行構造對象的工作,這是調用一個構造函數,在進入函數體之后,進行的是 對已經構造好的類對象的賦值,又調用個拷貝賦值操作符才能完成(如果并未提供,則使用編譯器提供的默認按成員賦值行為)
舉個例說明
class A;
class B
{public:
B(){a = 3;}
private:
A a;
}
class A
{public:
A(){}
A(int){value = 3;}
int value;
}
像上面,我們使a對象的value為3,調用一個A的構造函數+一個默認拷貝賦值符,才達到目的
B::B():a(3){}
像這樣,只調用了一個構造函數就達到了所需的對象啦,所以性能好的
轉載他人一篇
我的問題是關于初始化C++類成員的。我見過許多這樣的代碼(包括在你的欄目中也見到過):
{
x=0;
y=1;
}
{
}
回答
從技術上說,你的程序員朋友是對的,但是在大多數情況下,兩者實際上沒有區別。有兩個原因使得我們選擇第二種語法,它被稱為成員初始化列表:一個原因是必須的,另一個只是出于效率考慮。
讓我們先看一下第一個原因――必要性。設想你有一個類成員,它本身是一個類或者結構,而且只有一個帶一個參數的構造函數。
public:
CMember(int x) { ... }
};
CMember* pm = new CMember; // Error!!
CMember* pm = new CMember(2); // OK
如果Cmember是另一個類的成員,你怎樣初始化它呢?你必須使用成員初始化列表。
CMember m_member;
public:
CMyClass();
};
//必須使用成員初始化列表
CMyClass::CMyClass() : m_member(2)
{
•••
}
第二個原因是出于效率考慮,當成員類具有一個缺省的構造函數和一個賦值操作符時。MFC的Cstring提供了一個完美的例子。假定你有一個類CmyClass具有一個Cstring類型的成員m_str,你想把它初始化為"yada yada."。你有兩種選擇:
// 使用賦值操作符
// CString::operator=(LPCTSTR);
m_str = _T("yada yada");
}
//使用類成員列表
// and constructor CString::CString(LPCTSTR)
CMyClass::CMyClass() : m_str(_T("yada yada"))
{
}
或者memset(this,0,sizeof(this));
注意第二個片斷絕對是非面向對象的。
當我考慮初始化列表的問題時,有一個奇怪的特性我應該警告你,它是關于C++初始化類成員的,它們是按照聲明的順序初始化的,而不是按照出現在初始化列表中的順序。
CMyClass(int x, int y);
int m_x;
int m_y;
};
CMyClass::CMyClass(int i) : m_y(i), m_x(m_y)
{
}
|
新聞熱點
疑難解答
圖片精選