在类初始化和初始化列表中

时间:2013-10-18 14:33:29

标签: c++ c++11 initializer-list in-class-initialization

我最近发现你不能同时在类初始化和初始化列表中。 以下代码失败:

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

如果我删除了类初始化,初始化列表工作正常!

有人可以解释我为什么不允许这样的事情?

2 个答案:

答案 0 :(得分:7)

实际上这在C ++ 14中是允许的。

struct s
{
    int i=0;    
};

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

您的编译器可能没有在C ++ 14中实现新规则。然而,clang的最新版本接受了这一点,并且在C ++ 14模式下做了正确的事情。

当向C ++ 11添加了类内初始化时,它被指定为阻止类成为聚合。之所以这样做,是因为当时聚合概念与PoD类型密切相关,而PoD类型需要是可以轻易构建的。具有类内初始化意味着类型不再是简单的可构造的。然而,从那以后,这两个概念变得更加独立,因此对于C ++ 14来说,一个反对该决定的简短提议被接受了。

答案 1 :(得分:4)

这个初始化:

s s1 = { 42 };

要求s聚合,或者它有一个有效的构造函数,例如int或std::initializer_list

在声明点添加成员初始化时,您将类s呈现为非聚合,因此您不能再使用聚合初始化。

您可以通过添加构造函数为非聚合使用相同的初始化语法

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

我相信这个限制已经放宽了C ++ 14。

有关详细信息,请参阅What are aggregates...