标准中是否允许:
struct A
{
int a = 3;
int b = 3;
};
A a{0,1}; // ???
这个类仍然是聚合的吗?
clang
接受此代码,但gcc
不接受。
标准中是否允许:
struct A
{
int a = 3;
int b = 3;
};
A a{0,1}; // ???
这个类仍然是聚合的吗?
clang
接受此代码,但gcc
不接受。
在 C++11 中,具有类内成员初始值设定项使结构/类不是聚合——然而,这在 C++14 中有所改变。这是我第一次遇到它时发现的令人惊讶的事情,这种限制的基本原理是类内初始化器与用户定义的构造器非常相似,但相反的论点是没有人真正期望添加类内初始化器应该使他们的类/结构是非聚合的,我肯定没有。
从草案 C++11 标准部分8.5.1
Aggregates(强调我的未来):
聚合是一个数组或一个类(第 9 条),没有用户提供的构造函数(12.1),没有非静态数据成员的大括号或等号初始化程序(9.2),没有私有或受保护的非静态数据成员(第9 条) 11),没有基类(第 10 条),也没有虚函数(10.3)。
在C++14中,同一段内容如下:
聚合是一个数组或一个类(第 9 条),没有用户提供的构造函数(12.1),没有私有或受保护的非静态数据成员(第 11 条),没有基类(第 10 条),也没有虚函数(10.3) )。
N3605中涵盖了此更改:具有以下摘要的成员初始化程序和聚合:
Bjarne Stroustrup 和 Richard Smith 提出了一个关于聚合初始化和成员初始化器不能一起工作的问题。本文建议通过采用 Smith 提出的措辞来解决该问题,该措辞消除了聚合不能具有 member-initializers 的限制。
这条评论基本上总结了不愿让它们成为聚合体:
聚合不能有用户定义的构造函数,而 成员初始化器本质上是某种用户定义的构造函数(元素)(另请参见核心缺陷 886)。我不反对这种扩展,但它也对我们的聚合模型实际上是什么有影响。接受此扩展后,我想知道如何教授聚合是什么。
更新
emsr 指出G++ 5.0 现在支持使用非静态数据成员初始化器的 C++14 聚合,使用std=c++1y
或-std=c++14
:
struct A { int i, j = i; };
A a = { 42 }; // a.j is also 42
看到它在现场工作。