2013-08-12 51 views
19
struct SS {int a; int s;}; 

int main() 
{ 
    vector<SS> v; 
    v.push_back(SS{1, 2}); 
} 

該代碼可以編譯沒有任何錯誤。但是,當結構在類中初始化時,我得到編譯錯誤。任何人都可以解釋嗎?C++ 11結構初始化編譯錯誤

struct SS {int a = 0; int s = 2;}; 

錯誤:

In function ‘int main()’: 
error: no matching function for call to ‘SS::SS(<brace-enclosed initializer list>)’ 
    v.push_back(SS{1, 2}); 
         ^
note: candidates are: 
note: constexpr SS::SS() 
struct SS {int a = 0; int s = 2;}; 
     ^
note: candidate expects 0 arguments, 2 provided 
note: constexpr SS::SS(const SS&) 
note: candidate expects 1 argument, 2 provided 
note: constexpr SS::SS(SS&&) 
note: candidate expects 1 argument, 2 provided 

回答

28

在C++ 11,當您使用非靜態數據成員的初始化在聲明中對像你這樣在這裏:

struct SS {int a = 0; int s = 2;}; 

您做出A級非聚合。這意味着你可以不再初始化這樣一個實例:

SS s{1,2}; 

如要針對非集合這個初始化語法的工作,你就必須增加兩參數的構造函數:

struct SS 
{ 
    SS(int a, int s) : a(a), s(s) {} 
    int a = 0; 
    int s = 2; 
}; 

這限制已在C++ 14中解除。

請注意,您可能想要爲該類添加默認構造函數。用戶提供的構造函數的存在會禁止編譯器生成默認的構造函數。

查看相關閱讀here

+3

對,我正要回答相似。通過添加自定義構造函數SS(){}',可以看出沒有C++ 11特性。 – hvd

+4

C++ 14將不再使用類內初始化程序排除聚合;請參閱http:// www。open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3653.html – bames53

+1

@ bames53謝謝,我不知道。這是一個好消息。我覺得這個特別的規則過分限制。 – juanchopanza

4

默認成員初始的使用呈現類/結構一個非集合:

§8.5.1骨料

聚集是一個數組或類(第9)與沒有用戶提供的構造函數(12.1),對非靜態數據成員(9.2),沒有私有或受保護的非靜態數據成員(第11章),沒有基類(第10章),沒有支撐或等同初始化器。 ,沒有虛擬功能(10.3)。

語義差異,聚集體和非聚集體:

聚集體(例如,數組和結構):

Initialize members/elements beginning-to-end. 

非聚集體:

Invoke a constructor. 

v.push_back(SS{1, 2}); // Error, it tries to call SS constructor 

這意味着你現在需要一個構造函數:

struct SS 
{ 
    SS(int a, int s) : a(a), s(s) 
    { 
    } 
    int a = 0; 
    int s = 2; 
}; 
+0

有趣的是,在C++ 1y中,這不再是真的,聚合成員被允許使用括號或等號。 N3690§8.5.1/ 7提到了從加載初始化列表初始化聚合:「如果列表中的*初始化子句*少於聚合中的成員,則未初始化的每個成員 應從它的* brace-equal-initializer *或者如果沒有* brace-or-equal-initializer *, 從一個空的初始化列表(8.5.4)。「 – Casey

-7

struct SS {int a = 0,int s = 2;};

交換分號爲逗號,也許 我'只是一個

+0

偶結構本身不會編譯 – RiaD

+0

不,這不會回答這個問題。 – soon