2016-12-06 60 views
1

我很好奇C++ 11列表初始化。我定義了一個類:爲什麼在這種情況下複製構造函數匹配?

class base{ 
    base() { cout << "default ctor" << endl;} 
    base(std::initiazer_list<base> il) { cout << "list initialization << endl;} 
    base(const base &rhs) { cout << "copy ctor" << endl;} 
} 

在主函數中,我初始化兩個對象來測試我的類。

int main() 
{ 
    base obj{}; // default ctor 
    base obj2{obj}; // copy ctor 
} 

我從「有效的現代C++」調用使用列表的初始化語法強烈希望重載採取std::initializer_list學習。 因此,就我而言,我認爲第二個ctor會被調用,但是第三個調用會被調用。

你能解釋一下爲什麼嗎?

+0

首先,這不是真正的代碼。其次,你的編譯器/版本是什麼?這方面的規則經歷了一些近期的變化。 –

+0

我知道我的代碼沒有一些實際意義。我在Visual Studio 2017RC中測試我的代碼。 – linyuwang

+0

我不在乎「實際意義」。這顯然不是你測試的代碼。 –

回答

0

Demo

default ctor 
copy ctor 
list initialization 

因此,它是在第一個拷貝構造函數被調用拷貝到obj然後std::initializer_list<base>適當的構造函數重載(這是一個用於初始化列表)被稱爲感正確的。

base obj2{obj}; // copy ctor 

正如你所看到的,這包括兩個調用,而不是一個。一個要複製,一個要列出初始化。列表初始化器是強烈首選的重載。該副本將初始化該超載的參數。

編輯:gcc和clang因版本而異。

GCC Head Clang Head

我認爲發生的事情是,libstdc++實施std::initializer_list創建臨時對象,而鐺拿起拷貝構造函數,而不是初始化列表超載。

編輯2: 我檢查了這個在我的本地系統上,鐺-stdlib=libstdc++確實創建了臨時的std::initializer_list,因此調用複製構造函數存在。

所有編譯器都正確

+0

感謝您的回答。在我的IDE(Visual Studio 2017RC)中,我的代碼輸出與你的代碼不一樣。那麼,你的意思是它取決於編譯器? – linyuwang

+0

@linyuwang請檢查編輯。它依賴於標準的庫實現和編譯器。 – themagicalyang

+0

Clang處於一種奇怪的狀態:它實現了CWG1467(其中包括 - 這表示這是複製構造函數),但不是CWG2137(它將CWG1467的這部分恢復爲非聚合)。 –

相關問題