35

标准中是否允许:

struct A
{
  int a = 3;
  int b = 3;
};

A a{0,1}; // ???

这个类仍然是聚合的吗? clang接受此代码,但gcc不接受。

4

1 回答 1

44

在 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)。我不反对这种扩展,但它也对我们的聚合模型实际上是什么有影响。接受此扩展后,我想知道如何教授聚合是什么。

2013年5月通过了修订版N3653

更新

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

看到它在现场工作。

于 2014-11-25T03:52:55.373 回答