首页 > 解决方案 > 为什么在已删除的默认 ctor 旁边定义一个空的副本 ctor 会使空列表的值初始化失败?

问题描述

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

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
}

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

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

标签: c++c++11language-lawyerdefault-constructorvalue-initialization

解决方案


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

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

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


推荐阅读