使用已删除的构造函数进行C++ 14值初始化

Bik*_*eev 39 c++ language-lawyer c++14

我有一些误解:

让我们将struct A的默认构造函数标记为已删除:

struct A
{
  A() = delete;
};
Run Code Online (Sandbox Code Playgroud)

下一条指令格式正确,有什么影响?:

A a{};
Run Code Online (Sandbox Code Playgroud)

cppreference 值启动:

1)如果T是没有默认构造函数的类类型,或者是用户提供的默认构造函数或者删除了默认构造函数,则该对象是默认初始化的.

但是然后默认初始化的效果是:

如果T是类类型,则调用默认构造函数以提供新对象的初始值.

或者它是聚合初始化?谢谢!

use*_*016 30

struct A是:

  • 具有以下类的类类型:
    • 没有用户提供的构造函数1,
    • 没有私有或受保护的非静态数据成员,
    • 没有基类,
    • 没有虚拟成员功能.

因此,根据第8.5.1/1节提供的定义,它符合聚合类型.

然后是聚合初始化优先于值初始化的优先级.该标准表示聚合初始化优先于价值初始化(草案N3936,第8.5.4/3节,第201页)(强调我的)

列表初始化对象或类型T的引用定义如下:

  • 如果T是聚合,则执行聚合初始化(8.5.1).
  • 否则,如果初始化程序列表没有元素且T是具有默认构造函数的类类型,则对象将进行值初始化.
  • [...更多规则...]

(1) 根据关于为什么删除的构造函数不算作用户定义的注释中的要求,这是标准所说的内容(草案N3936,第8.4.2/5节,第198页):

如果函数是用户声明的,并且在第一个声明中未明确默认或删除,则用户提供该函数.


jua*_*nza 20

它结构良好.A是聚合1,并且根据草案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]中:

如果函数是用户声明的,并且在第一个声明中未明确默认或删除,则用户提供该函数.

  • +1这是*用户提供的*条款让我失望.我假设显式默认/删除的构造函数按用户提供的方式计算. (3认同)
  • +1哦加油,30秒差异! (2认同)
  • +1 for*"如果用户声明并且未明确默认**或在第一次声明中删除**,则用户提供了一个函数**."*....*删除*部分让我感到惊讶! (2认同)
  • @Nawaz我总是要查找这个"用户提供的"业务.希望我从现在开始记住它.但是[某些编译器似乎弄错了]并没有帮助(http://ideone.com/n3q3kO). (2认同)
  • @Yakk是的,我倾向于认为这是一个缺陷.删除构造函数应该是提供私有空库的干净版本...... (2认同)