今天在做《面試筆試寶典》的時候,遇到了初始化列表和構造函數初始化區別的問題。之前只是知道有些情況必須用初始化列表,並且初始化列表的效率要高。但是要是說兩者的區別,還真是沒有探究過。網上搜了一些博客,對我很有幫助,但是感覺沒有講到自己異或的地方。所以自己實踐了一下。
首先,我們來把兩者的一般原型給出:
初始化列表方式:
Object::Object(itn _x,int _y):x(_x),y(_y) { }
構造函數初始化:
Object::Object(int _x,int _y) { x = _x; y = _y; }
初始化列表和構造函數初始化(賦值)的方式對於內置類型的成員(如int等)來說,其實沒有什么區別,其性能和結果往往一樣。
但是,對於非內置類型的成員(類類型)來說,是有區別的。
我們舉個栗子:
這是CMember類
#ifndef _CMEMBER_H_ #define _CMEMBER_H_ #include <iostream> using namespace std; class CMember { public: CMember() { cout << "CMember constructor 1" << endl; cmember = 0; } CMember(CMember& obj) { cout << "CMember copy constructor" << endl; } CMember(int _cmember) { cout << "CMember constructor 2" << endl; cmember = _cmember; } CMember& operator =(CMember& obj) { cout << "CMember =" << endl; return *this; } int cmember; }; #endif _CMEMBER_H_
這是MClass類
#ifndef _MCLASS_H_ #define _MCLASS_H_ #include <iostream> using namespace std; #include "CMember.h" class MClass { //MClass(CMember& _cm) :cm(_cm) //{ // //cm = _cm; //} public: MClass(CMember& _cm) //注意這里我們用的是引用,如果沒有用引用,則會多一次copy構造函數的調用 { cm = _cm; } CMember cm; }; #endif _MCLASS_H_
因為編譯器總是確保所有成員對象在構造函數體執行之前初始化,所以類類型的數據成員對象,在進入構造函數體之前已經完成構造。例子中編譯的代碼將調用CMember:: CMember()來初始化cm(這里調用一次CMember構造函數),這在控制到達賦值語句前完成。接下來有調用一個賦值運算符函數。結果是調用了兩個Cstring函數(構造函數和賦值操作符)。
我們測試一下:
#include <iostream> using namespace std; #include "CMember.h" #include "MClass.h" void main() { CMember c1(1); MClass m1(c1); getchar(); }
輸出如下:
下面我們試一下,初始化列表方式。
MClass(CMember& _cm) :cm(_cm)
{
}
輸出:
只調用一次copy構造函數。