C++中的複製初始化與直接初始化
C++ Primer裡說過,在C++中,初始化不等於賦值,初始化是指建立變數並給變數賦初值,而賦值是指擦除變數的當前值並用新值替換。C++中有兩種初始化方法,直接初始化和複製初始化。直接初始化是指使用 Object obj(patamer)這樣的語句,Object可以是內建型別或者使用者自定義的類型別;而複製初始化是指Object obj = obj1。
1)內建型別的初始化
以int型為例:
int a = 5 // 複製初始化
int b(5); // 直接初始化
對於內建型別來說這兩種初始化沒有任何差別。
2)類物件的初始化
class Base
{
public:
Base() {cout<<"Base::Base()"<<endl; } // 預設建構函式
Base(int i) {cout<<"Base::Base(int i)"<<endl; } // 帶一個整形引數的建構函式
Base(const Base& base) {cout<<"Base(const Base& base)"<<endl; } // 拷貝建構函式
Base& operator= (const Base& base) { cout<<"operator="<<endl; return *this;} // 複製操作符
};
以類Base為例,首先宣告,以上程式碼併為考慮成員函式的正確與否。
Base base1; //呼叫預設建構函式
Base base2(1); //呼叫帶一個整形引數的建構函式
Base base3(base2);// 呼叫拷貝建構函式
Base base4 = base1;//呼叫拷貝建構函式
總之,對於類型別,直接初始化呼叫預設建構函式或者與初始化時提供的引數相匹配的建構函式(注意,包括拷貝建構函式);而複製初始化則呼叫拷貝建構函式。
說到這裡,順便提下建構函式初始化列表
3)建構函式初始化列表
假設有一個類:
class Test
{
public:
Test(){ _base = Base();}
Test(int i) : _base(i) {};
Test(const Base& base) : _base(base) {};
Base _base;
};
同樣C++ primer中,說過這樣一句話,大概意思是,建構函式分為兩部分:初始化和賦值,在建構函式初始化列表裡進行的是初始化,呼叫與提供的引數匹配的建構函式來初始化成員變數。而在建構函式的一對大括號之間,則進行的是賦值,既然是賦值,那麼就說明已經進行了初始化,這個初始化過程是通過呼叫預設建構函式來實現的,在大括號裡面進行的是賦值操作,呼叫的是賦值操作符。
如:
Test = t1; // 先呼叫預設建構函式Base()初始化_base,然後在呼叫複製操作符對_base進行賦值
Test t2(1); // 直接呼叫帶一個整形引數的建構函式Base(int i)初始化_base
Base base5;
Test t3(base5);//直接調拷貝建構函式Base(const Base& base)初始化_base
注意:如果成員變數所屬的類如果沒有預設建構函式,那麼就必須採用建構函式初始化列表的方式進行初始化。
對於使用者自定義的類型別的成員變數來說,應該採用初始化列表的方式進行初始化,這樣就省略了賦值的過程,提高了效率;而對於內建內型,差別不大。