为什么在已删除的默认构造函数旁边定义一个空副本构造函数会使空列表的值初始化失败?

Enr*_*lis 5 c++ default-constructor language-lawyer value-initialization c++11

简而言之,为什么下面的代码表现得像评论中描述的那样?

struct A
{
    A() = delete;
    //A(const A&) {} // uncommenting this...
};

int main()
{
    A a{}; // ... breaks this
    //A(); // this fails in either case because of `A() = delete;` only
}
Run Code Online (Sandbox Code Playgroud)

我应该查看标准的哪一部分(或至少是 cppreference 上的一页)来理解这一点?

但是,写入A(const A&) = default;而不是//A(const A&) {} 不会中断A a{};。那这个呢?我认为根本原因是相同的,但是真正了解 C++ 的人的一句话比我认为的要好。

Sto*_*ica 10

如果没有用户提供的复制构造函数,A则是聚合。是的,即使我们删除了默认构造函数。这是在 C++20 中解决的问题

因此,在 C++20 之前,A a{};聚合初始化,因此不使用已删除的构造函数。当您取消对复制构造函数的注释时,A不再是聚合,从而将聚合初始化转换为值初始化。所以初始化时a会尝试调用被删除的构造函数。

为了从标准中推测初始化器的含义,通常从[dcl.init]/16 开始。通过项目符号,您可以发现初始化程序的属性(当与相关类型的属性匹配时)将如何影响初始化发生的方式。

  • 我认为仅此一点就足以证明 C++ 只对专家友好的声誉。 (2认同)