c++中類的建構函式寫法有兩種,一種是使用初始化列表,一種是在**塊中賦值。很多書中(包括c++ primer、c++ primer plus等等)都會提到應該盡量使用初始化列表而不是在**塊中賦值,因為使用初始化列表通常比在**塊中賦值效率要高。但是這個結論是怎麼來的?如何驗證呢?今天我們來設計乙個小例子對比一下兩者之間的區別。
首先,我們定義乙個man類,資料成員包括姓名和年齡。設計很簡單,直接放**:
public:
man(
)man
(string n,
int a)
:name
(n),
age(a)
man(
const man& a)
man& operator=
(const man& a)
private:
string name;
int age;
};
在這個類裡面,我們寫了三個建構函式:預設建構函式,帶參的建構函式、拷貝建構函式,並且過載了賦值運算子。同時在每個函式當中新增了列印語句,指示當前執行的函式名稱。
我們再來定義乙個chineseman類。類中包含乙個man物件和乙個名為id的string物件,用來儲存身份證號碼。
class chineseman
private:
string id;
man man;
};
在類中我們我們寫了乙個帶引數的建構函式,用**塊賦值的方式來初始化。然後我們再來寫乙個測試程式:
int
main()
測試程式中建立了乙個man物件和乙個chineseman物件,chineseman物件用man物件來初始化。看一下程式執行的結果。
$ ./a.exe
call man::man(string, int)
-----------
call man::man(const man&)
call man::man()
call man::operator=(const man& a)
從執行結果來看:在main函式中首先呼叫了man的帶參建構函式,建立了物件vincent,這個很好理解。下面來看看建立vincent_cn的過程中,稍微有點繞。建立vincent_cn的過程可以分為三步:
首先呼叫了man的拷貝建構函式,因為需要把實參vincent拷貝賦值給形參a;
然後又呼叫了man的預設建構函式,這是因為需要建立vincent_cn物件的man成員。
第三步呼叫賦值運算子函式,把物件a賦值給物件man。至此完成vincent_cn的構造過程。
可以看出,用**塊初始化乙個引數含物件的物件,經歷了三步。如果傳入的引數是引用或者指標的話,第一步可以省掉。我們再看一下用初始化列表構造物件是什麼樣子。
下面我們把chineseman類的建構函式修改一下,改為初始化列表:
class chineseman
private:
string id;
man man;
};
測試程式不變,再來看一下執行結果:
$ .
/a.exe
call man:
:man
(string,
int)
----
-------
call man:
:man
(const man&
)call man:
:man
(const man&
)
程式執行結果的第一行是建立vincent物件,建立vincent_cn的過程可以分為兩步:
第一步呼叫拷貝建構函式,是因為傳遞引數需要把實參vincent傳遞給形參a。
第二步再次呼叫拷貝建構函式,是用形參a來構造資料成員man。
因此用初始化列表構造物件,呼叫了兩次拷貝建構函式。
對比兩種方法的執行結果,可以看出來:用初始化列表構造物件,在實參傳給形參之後,直接就呼叫拷貝建構函式用形參來構造資料成員了,不需要經歷先構造再賦值的操作。因此效率上確實要比**塊初始化高一些。在這樣乙個短短的程式上看不出來什麼明顯的效果,但是如果乙個類的資料成員裡面包含了大量的其他類物件,那麼累積起來的效果是非常客觀的,因此在平常的開發過程中我們應該養成盡量使用列表初始化來構造物件的習慣。
the end
兩種排序方法的效率比較
前提 筆記本測試,效能一般,測試前開了好多記憶體殺手。唯一變數 陣列的長度,其餘各項均不發生變化。此測試不具有一般性 資料量太少,實驗重複次數不夠,沒有空白對比試驗 聽著怎麼像是生物實驗了 如果感興趣,可以自己做重複實驗。第一種,經典的氣泡排序,如下 a long start system.curr...
重寫構造方法實現兩種功能
要求使每個新建立出來的物件都有乙個自定義的預設值 實現 instancetype initwith int age 思考 實現 建立乙個學生類student,通過重寫構造方法實現建立學生物件的時候,預設的年齡的值為指定的年齡 student.h import inte ce student nsob...
Python兩種列表翻轉方法的效率比較
python兩種列表翻轉方法的效率比較 編寫乙個python程式,實現將一堆數字新增到乙個初始為空的列表中,然後翻轉該列表。方法一 使用列表的reverse 方法實現 方法二 使用列表的insert 方法實現 nums2 for i in range count nums2.insert 0,i 在...