2013-08-12 44 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