2013-10-18 134 views
3

我最近發現你不能同時在類初始化和初始化列表中。 下面的代碼失敗:在類初始化和初始化列表

struct s 
{ 
    int i=0;  
}; 
int main() { 
    s s1; //s1.i = 0 
    //s s2={42}; //fails 
    return 0; 
} 

如果我刪除了在類初始化,初始化列表中工作正常!

有人可以解釋爲什麼這樣的事情是不允許的?

+1

您確定您使用C++ 11模式進行編譯嗎?編譯器是否真的實現了它?你有哪個編譯器和哪個版本? –

回答

7

事實上,這在C++ 14中是允許的。

struct s 
{ 
    int i=0;  
}; 

int main() { 
    s s1; 
    s s2 = {42}; // succeeds 
} 

很可能您的編譯器並未在C++ 14中實現新規則。然而,最新版本的clang接受這一點,並在C++ 14模式下執行正確的操作。

當將類內初始化添加到C++ 11時,它被指定爲阻止類成爲聚合。這是因爲當時聚合概念與需要簡單構建的PoD類型密切相關。擁有一個類內初始化意味着一個類型不再是可以構造的。然而,從那以後,這兩個概念變得更加獨立,因此對於C++ 14來說,一個反轉該決定的簡短提議就被接受了。

+0

它不符合GCC 4.8。 – thokra

+1

我不認爲它在C++ 11中是合法的。看到我的答案。 – juanchopanza

+0

也沒有鏗鏘聲++ 5.0 – chrizke

4

這個初始化:

s s1 = { 42 }; 

要求s,或者說,它有一個有效的構造以e.g一個int或std::initializer_list

當您在聲明的位置添加成員初始化時,您將類s渲染爲非聚合,因此您不能再使用聚合初始化。

你可以通過添加一個構造函數中使用相同的初始化語法你非集合:

struct s 
{ 
    s(int i) : i(i) {} 
    int i=0;  
}; 

我相信這個限制已經放寬了對C++ 14。

查看What are aggregates...瞭解更多信息。

+0

這不是一個解釋。問題是爲什麼聚合可能沒有爲其成員提供大括號或相等的初始值設定項。 –

+0

@ VladfromMoscow,因爲標準是這樣說的。這裏沒有任何解釋,但我想人們意識到,放棄C++ 14的這個規則已經足夠安全了。 – juanchopanza

+0

我也來到這個解決方法,但它正是我想避免 – Davidbrcz