具有已删除的默认构造函数的类类型是否可以默认初始化?

big*_*iao 6 c++ initialization language-lawyer c++11

从cppref所说的值初始化

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

但由于该类类型已删除默认构造函数,该对象如何进行默认初始化?

据我所知,类类型的默认初始化需要访问默认构造函数.如果我们有:

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

然后A *a = new A;会失败,也会失败A* a = new A();.

但是A a{};没关系.但为什么?根据cppreference

否则,如果braced-init-list为空且T是具有默认构造函数的类类型,则执行值初始化.

son*_*yao 7

我认为标准只是意味着"如果T是具有已删除的默认构造函数的类类型,则转到默认初始化".它最终会失败,因为删除了为默认初始化选择的构造函数.它用于区分第二种情况,即"if T是具有默认构造函数的类类型,既不是用户提供也不是删除",对于这种情况,首先执行零初始化,然后默认初始化,如果T有非平凡的话默认构造函数.

A a{} 没关系,但为什么呢?

因为何时A聚合类型聚合初始化被执行.请注意,自C++ 11以来,允许显式删除的构造函数用于聚合类型.

在所有情况下,如果使用空的大括号{}并且T是聚合类型,则执行聚合初始化而不是值初始化.

聚合是以下类型之一:

  • 数组类型
  • 类类型(通常是struct或union),具有
    • 没有私有或受保护的非静态数据成员
    • 没有用户提供的, inherited, or explicit (since C++17)构造函数(explicitly defaulted or deleted constructors are allowed) (since C++11)


Bar*_*rry 5

但由于该类类型已删除默认构造函数,该对象如何进行默认初始化?

声明对象是默认初始化的,本身并不意味着默认初始化是一件有效的事情.措辞只是将我们转移到该过程中,它使初始化过程连贯,并不意味着它必须成功.

例如:

struct A {
    A() = delete;
    A(int); // not an aggregate
};

auto a = A(); 
Run Code Online (Sandbox Code Playgroud)

初始化器是(),所以这个对象是值初始化的.在这种情况下,这意味着它是默认初始化的,这意味着我们找到了一个构造函数.

调用构造函数恰好是格式错误的,因为它被删除了,这使整个初始化格式不正确.但是我们通过默认初始化来达到这一点.