有人可以指出我,对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'
答案 0 :(得分:5)
以下语法:
abc a = {1, MY::A};
是列表初始化,根据正在初始化的类型,它可以执行不同的操作。如果没有非静态数据成员初始值设定项(/*{123};*/
),您的结构就是一个聚合,并且大小写在[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])。
[注意:聚合初始化不允许访问受保护和私有基类'成员或构造者。 - 结束记录]