2013-04-17 178 views
3

我是C++編程的初學者,我有一個關於C++類構造函數的簡單問題。 爲以下代碼片段調用構造函數多少次?構造函數被調用多少次?

std::string s = std::string("hello world"); 

我想這是兩個,對吧?第一個是字符串(const char * s),第二個是字符串(常量字符串& s)。如果我錯了,請糾正我。

接下來的問題是,如果我在釋放模式下編譯代碼,編譯器會自動優化它嗎?例如把它當作std::string s("hello world");不同的編譯器有不同的行爲嗎?

+0

檢查C++ 11中的移動構造函數。 –

+0

C++ 03的行爲是什麼? –

回答

4

複製初始化(與=)其中源類型與目標類型相同的行爲非常像直接初始化。因此,初始化相當於:

std::string s(std::string("hello world")); 

沒有優化,將按您所述調用兩個構造函數。在C++ 11中,移動構造函數將優先用於第二步(定義爲string(string&&)),因爲std::string("hello world")是一個右值表達式。然而,標準明確地允許在某些情況下拷貝/移動省音,包括這一個:

當尚未結合至參考(12.2)臨時類對象將被複制/移動到一個類用相同的CV-非限定類型的對象中,複製/移動操作可以通過直接構建臨時物體插入省略副本的目標可以省略/移動

因此,編譯器可以,如果它選擇,優化走複製。請注意,即使複製構造函數有一些奇怪的副作用,編譯器也可能會這樣做。也就是說,一個完美定義和有效的C++程序可能有多個可能的執行路徑。一般來說,你想避免這種情況。

+0

爲了迂迴,它不是「完全一樣」,因爲隱式構造函數需要被複制初始化訪問,並且原則上覆制初始化允許編譯器調用兩個構造函數(實際上沒有任何理性的編譯器會這麼做)。 –

+0

@KerrekSB對我而言,措辭不好。 「完全」改爲「非常」。但是,這兩種形式都可以調用兩個構造函數,不是嗎? –

+0

直接初始化可能*不*調用兩個構造函數,我非常確定......實際上,非常確定,因爲您可以刪除複製構造函數並仍然執行直接初始化。 –

3

您的代碼符合複製elision的條件,因此除非明確指示不要這樣做,否則大多數理智編譯器將始終如此對待,如std::string s("hello world");