【问题标题】:C++11 default class member initialization with initializer list , simultaneouslyC++11 默认类成员初始化与初始化列表,同时
【发布时间】:2017-08-23 08:52:14
【问题描述】:

有人可以请我指出 C++ 标准的相应段落,或者如果我取消注释文本 ({123}),也许可以提供一些解释为什么我的代码无法编译?

一般来说,我理解使用默认成员初始化和通过初始化列表进行初始化有什么问题,但我无法指出确切的原因。

enum class MY: int
{
    A = 1
};

struct abc
{
    int a;/*{123};*/  //compilation failed if uncommented
    MY m;
};

abc a = {1, MY::A};

编译器错误,如果文本没有注释:

错误:无法将“{1, A}”从“”转换为“abc”

【问题讨论】:

  • 在 C++11 中,NSDMI 的使用使您的结构不是聚合。在 C++14 中,这已经改变了 iirc
  • 是的,所以如果你用-std=c++14编译,你就没事了。
  • 如果是这样的话,它值得另一个答案!

标签: c++ c++11


【解决方案1】:

以下语法:

abc a = {1, MY::A};

是一个列表初始化,根据被初始化的类型,它的执行可能会有所不同。如果没有非静态数据成员初始值设定项 (/*{123};*/),您的结构是一个聚合,并且 case 属于 [dcl.init.list]/p3

  • 否则,如果T 是聚合,则执行聚合初始化。

但是,要成为聚合类型,在 C++11 中必须满足以下条件:

聚合是一个数组或一个类(第 9 条),没有用户提供的构造函数 (12.1),非静态数据成员没有大括号或等式初始化器 (9.2),没有私有或受保护的非静态数据成员(第 11 条),没有基类(第 10 条),也没有虚函数(10.3)。

也就是说,NSDMI(非静态数据成员初始化)的使用打破了上述规则集,结果,这种类型的实例不能再进行列表初始化。

这条规则在 C++14 中有所改变,目前的措辞为[dcl.init.aggr]/p1:

聚合是一个数组或一个类

  • (1.1) 没有用户提供的、显式的或继承的构造函数 ([class.ctor]),

  • (1.2) 没有私有或受保护的非静态数据成员 ([class.access]),

  • (1.3) 没有虚函数,并且

  • (1.4) 没有虚拟、私有或受保护的基类 ([class.mi])。

[ 注意:聚合初始化不允许访问受保护和私有基类的成员或构造函数。 — 尾注 ]

【讨论】:

    猜你喜欢
    • 2019-09-10
    • 2015-03-22
    • 1970-01-01
    • 2020-02-08
    • 1970-01-01
    • 2016-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多