我有一些误解:
让结构A的默认构造函数标记为已删除:
struct A
{
A() = delete;
};
下一条指令格式正确,有什么影响?:
A a{};
来自cppreference value initilization:
1)如果T是没有默认构造函数或带有的类类型 用户提供的默认构造函数或删除的默认值 构造函数,该对象是默认初始化的。
但是默认初始化的效果是:
如果T是类类型,则调用默认构造函数来提供 新对象的初始值。
或者它的聚合初始化? 谢谢!
答案 0 :(得分:30)
您的struct A
是:
因此,根据第8.5.1 / 1节提供的定义,它符合聚合类型。
然后是聚合初始化优先于值初始化的优先级。标准说聚合初始化优先于价值初始化(草案N3936,第8.5.4 / 3节,第201页)(强调我的)
对象或类型T的引用的列表初始化定义如下:
- 如果T是聚合,则执行聚合初始化(8.5.1)。
- 否则,如果初始化列表没有元素且T是具有默认构造函数的类类型,则该对象是值初始化的。
- [...更多规则......]
(1) 根据评论中关于为什么删除的构造函数不算作用户定义的请求,这是标准说(草案N3936,第8.4.2 / 5节,第198页):
如果函数是用户声明的,并且在第一次声明时未明确默认或删除,则该函数是用户提供的。
答案 1 :(得分:20)
结构良好。 A
是一个聚合 1 ,根据draft N3936,直接列表初始化中使用的空初始值设定项列表导致聚合初始化:
来自§8.5.4/ 3列表初始化[dcl.init.list] :
对象或类型T的引用的列表初始化定义如下:
- 如果T是聚合,则执行聚合初始化(8.5.1)。
[例如:
struct S2 { int m1; double m2, m3; };
....
S2 s23{}; // OK: default to 0,0,0
...
- 结束示例]
...
C ++ 11和C ++ 1y之间的相关变化是聚合情况下聚合与值初始化优先级的变化:
C ++ 11带领
对象或类型T的引用的列表初始化定义为 如下:
- 如果初始化列表没有元素而T是一个类 使用默认构造函数键入,该对象是值初始化的。
- 否则,如果T是聚合,则执行聚合初始化(8.5.1)....
接着是上面的例子。
C ++ 1y优先考虑聚合初始化:
对象或类型T的引用的列表初始化定义如下:
- 如果T是聚合,则执行聚合初始化(8.5.1)。
...
- 否则,如果初始化列表没有元素且T是具有默认构造函数的类类型,则该对象是值初始化的。
1 为什么A
是聚合的?
它是C ++ 11和C ++ 14中的聚合。
C ++ 1Y:
8.5.1聚合[dcl.init.aggr]
聚合是一个数组或类(第9条),没有用户提供的构造函数(12.1),没有私有或受保护的非静态数据成员(第11条),没有基类(第10条),没有虚拟功能(10.3)。
唯一不明显的部分是默认构造函数是否是用户提供的。它不是:
在§8.4.2[dcl.fct.def.default] :
如果函数是用户声明的而非显式的,则用户提供该函数 在第一份声明中默认或删除。