4

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

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

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

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

4

2 回答 2

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,接受了一个简短的提议来扭转该决定。

于 2013-10-18T14:44:31.850 回答
4

这个初始化:

s s1 = { 42 };

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

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

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

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

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

有关更多信息,请参阅什么是聚合...。

于 2013-10-18T14:42:08.347 回答