在聚合初始化之前的c++11值初始化
c++11 value-initialization prior to aggregate-initialization
我试图理解@bolov对删除默认构造函数问题的第一个接受的答案。对象仍然可以被创建…有时[1]
好像我在那里发现了一个错误,所以它把整个解释搞砸了。
@bolov解释了为什么这段代码可以在c++11中成功编译:
场景
struct foo {
foo() = delete;
};
// All bellow OK (no errors, no warnings)
foo f = foo{};
foo f = {};
foo f{}; // will use only this from now on.
以及为什么这段代码在c++11中编译失败:
情形C
struct foo {
foo() = delete;
foo(int) {};
};
foo f{}; // error call to deleted constructor
他说关键是第一个foo是聚合,第二个foo不是聚合。
然后他给出了cppreference的节选:
T类型对象的list初始化效果如下:…
- 如果T是聚合类型,则进行聚合初始化。这处理了场景A、B、D、E(和c++ 14中的F)
否则T的构造函数分两个阶段考虑:
所有以std::initializer_list为参数的构造函数
否则[…T的所有构造函数都参与重载解析[…]这处理C(和c++ 11中的F)…
根据摘录,当您在场景A中写入foo f {};时,您将获得聚合初始化。那就太好了。但实际上,在c++11(#3337草案,最接近标准)中,有不同的初始化顺序:
类型T的对象或引用的列表初始化定义如下:
- 如果初始化列表中没有元素,并且T是带有默认构造函数的类类型,则该对象进行值初始化。
- 如果T是聚合,则执行聚合初始化(8.5.1)
因此foo f {};在场景A应该导致值初始化,即调用DELETED默认构造函数,代码编译失败。
作为Core Issue 1301的结果,这是c++ 11的一个缺陷,列表初始化的优先级从:
类型T的对象或引用的列表初始化定义如下:
- 如果初始化列表中没有元素,并且T是带有默认构造函数的类类型,则该对象进行值初始化。
- 如果T是聚合,则执行聚合初始化(8.5.1)
:
类型T的对象或引用的列表初始化定义如下:
- 如果T是聚合,则执行聚合初始化(8.5.1)
- 否则,如果初始化列表没有元素,并且T是带有默认构造函数的类类型,则对该对象进行值初始化。
所以场景A中的foo{}
仍然是聚合初始化。
相关文章:
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 在 C++11 及更高版本中,有没有办法初始化初始值设定项列表中的向量?
- C++11 中的混合列表初始化
- 在 C++11 中轻松初始化模板类的静态成员,没有 clang 警告
- 为什么静态数据成员不能在c++11中的类中初始化
- C++11 默认类成员初始化与初始值设定项列表同时
- C++11默认初始化/值初始化/直接初始化
- C++11 整数初始化
- C++11 成员类初始化顺序
- 为什么 GCC 6.3 在没有显式 C++11 支持的情况下编译此大括号初始化列表代码
- 为什么编译器在试图初始化具有C 11样式的对象数组时隐含删除构造函数
- 如何在一行中初始化 C++11 中的 n 个相等元素的向量
- 仅初始化c++11元组的第一个参数
- 初始化 C++11 数组的最佳方法,主要是标识映射
- 我们什么时候应该使用括号 ( ) 与初始值设定项 { } 语法来初始化 C++11 中的对象
- 正在初始化C++11中要求为prvalue的表达式
- 从if语句中初始化C++11线程
- 初始化directX 11时出现未处理的异常错误
- 如何使用常规构造函数模式初始化 C++ 11 标准容器
- 如何正确初始化c++ 11 std::seed_seq