我试图理解@bolov 对已删除默认构造函数问题的第一个接受答案。仍然可以创建对象...有时[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 是聚合类型,则执行聚合初始化。这需要处理场景 ABDE(和 C++14 中的 F)
否则 T 的构造函数分为两个阶段:
所有采用 std::initializer_list 的构造函数...
否则 [...] T 的所有构造函数都参与重载决议 [...] 这会处理 C(和 C++11 中的 F)...
根据您编写时的摘录foo f { }; 在场景 A中,您将获得聚合初始化。那就太好了。但实际上在 c++11(#3337 草案,最接近标准)中,你有不同的初始化顺序:
类型 T 的对象或引用的列表初始化定义如下:
- 如果初始值设定项列表没有元素并且 T 是具有默认构造函数的类类型,则该对象是值初始化的。
- 否则,如果 T 是一个聚合,则执行聚合初始化 (8.5.1)
所以foo f { }; 在场景 A中应该导致值初始化,即会调用 DELETED 默认构造函数,并且代码应该编译失败。