从cppref所说的关于value initialization
的内容如果T是没有默认构造函数或使用用户提供的或已删除的默认构造函数的类类型,则对象为默认初始化;
但是由于该类类型有删除了默认构造函数,该对象如何进行默认初始化?
据我所知,类类型的默认初始化需要访问默认构造函数。如果我们有:
struct A {
A() = delete;
int k;
};
然后A *a = new A;
将失败,A* a = new A();
也会失败。
但是A a{};
没问题。但为什么?根据{{3}}
否则,如果braced-init-list为空且T是具有默认构造函数的类类型,则执行值初始化。
答案 0 :(得分:7)
我认为标准只是意味着“if T
是一个带有删除默认构造函数的类类型,然后转到默认初始化”。它最终会失败,因为删除了为默认初始化选择的构造函数。它用于区分第二种情况,即“if T
是具有默认构造函数的类类型,既不是用户提供也不是删除”,对于这种情况,首先执行零初始化,然后执行默认初始化T
有一个非平凡的默认构造函数。
A a{}
没问题,但为什么?
因为当A
是aggregate type聚合初始化时。请注意,自C ++ 11以来,允许显式删除的构造函数用于聚合类型。
在所有情况下,如果使用空的大括号{}并且T是聚合类型,则执行聚合初始化而不是值初始化。
和
聚合是以下类型之一:
- 数组类型
- 类类型(通常是struct或union),具有
- 没有私人或受保护的非静态数据成员
- 没有用户提供的
, inherited, or explicit (since C++17)
构造函数(explicitly defaulted or deleted constructors are allowed) (since C++11)
答案 1 :(得分:5)
但由于该类类型已删除默认构造函数,该对象如何进行默认初始化?
声明对象是默认初始化的,这本身并不意味着默认初始化是一件有效的事情。措辞只是将我们转移到该过程中,它使初始化过程连贯,并不意味着它必须成功。
例如:
struct A {
A() = delete;
A(int); // not an aggregate
};
auto a = A();
初始值设定项为()
,因此对象为value-initialized。在这种情况下,这意味着它是default-initialized,这意味着我们find a constructor。
调用该构造函数恰好是ill-formed,因为它被删除了,这使得整个初始化格式不正确。但是我们通过默认初始化来达到这一点。