【发布时间】:2016-09-20 07:49:23
【问题描述】:
我试图理解@bolov 对问题Deleted default constructor. Objects can still be created... sometimes [1] 的第一个公认答案
好像我在那里发现了一个错误,所以它搞砸了整个解释。
@bolov 解释了为什么这段代码可以在 c++11 中成功编译:
场景 A
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 类型的对象进行列表初始化的效果是: ...
- 如果 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 { };在scenario A应该导致值初始化,即调用DELETED默认构造函数,代码应该失败编译。
【问题讨论】:
-
我不知道你在问什么。
-
试图让它更简洁。
-
@Quentin,好吧,我会努力写的更好。
-
@Quentin,我已经重写了我的问题。
-
非常好,改进了很多!我在不同的初始化中有点迷失,但cppreference page for value initialisation 在任何描述之前声明,“在所有情况下,如果使用空括号
{}并且 T 是聚合类型,聚合初始化是执行而不是值初始化。”。
标签: c++ c++11 aggregate language-lawyer value-initialization