零规则 - 未生成默认构造函数

Rule of zero - default constructor not generated

提问人:code_fodder 提问时间:5/19/2021 最后编辑:YSCcode_fodder 更新时间:5/19/2021 访问量:273

问:

我正在读这个:https://en.cppreference.com/w/cpp/language/rule_of_three

我的理解是,如果你想有一个带有虚拟析构函数的基类,你需要定义所有 5 个特殊函数(从 0 部分的规则中提取):

class base_of_five_defaults
{
 public:
    base_of_five_defaults(const base_of_five_defaults&) = default;
    base_of_five_defaults(base_of_five_defaults&&) = default;
    base_of_five_defaults& operator=(const base_of_five_defaults&) = default;
    base_of_five_defaults& operator=(base_of_five_defaults&&) = default;
    virtual ~base_of_five_defaults() = default;
};

但是,当我尝试安装该类时,我收到错误说“未创建默认 c'tor”:

    base_of_five_defaults b; // Error

然后,如果我生成默认值,就可以了:

base_of_five_defaults() = default;

但我根本不明白这是必要的......所以我很困惑为什么它不存在。我认为编译器不生成默认构造函数的唯一原因是如果您指定了一个非默认构造函数......

如果您确实需要指定默认的 c'tor,那么示例中的类是不可构造的 - 这似乎很奇怪。

这是我的完整现场示例的链接: https://godbolt.org/z/qPvjd6r51


来自 https://en.cppreference.com/w/cpp/language/default_constructor

隐式声明的默认构造函数

如果没有用户声明 为类类型(struct、class、 或 union),编译器将始终将默认构造函数声明为 其类的内联公共成员。

我想这意味着如果声明了,那么即使它的“默认”,它也被认为是用户声明的?base_of_five_defaults(const base_of_five_defaults&) = default;

C++ 默认构造函数 零规则

评论

1赞 463035818_is_not_an_ai 5/19/2021
它旨在用作基类(尽管这并不能改变无法构造它的事实)
0赞 code_fodder 5/19/2021
@largest_prime_is_463035818但是基类可构造的,除非它被特别抽象......但我明白你的意思——我确实觉得这个例子有点奇怪:)
0赞 463035818_is_not_an_ai 5/19/2021
该示例与“C.21:如果您定义或=删除任何复制、移动或析构函数,请定义或=删除它们”相反,要么我遗漏了一些东西,要么他们只是错过了将其包含在示例中。其实我不确定该如何理解,是真正的用处,还是仅仅为了证明这一点?我倾向于后者base_of_five_defaults
0赞 Jean-Baptiste Yunès 5/19/2021
因为您定义了至少一个显式 ctor,因此隐式默认 ctor 被删除了?
0赞 463035818_is_not_an_ai 5/19/2021
哦,等一下。我误读了C21。它实际上没有提到构造函数。我一定缺少什么;)

答:

1赞 YSC 5/19/2021 #1

我想这意味着如果声明了,那么即使它的“默认”,它也被认为是用户声明的?base_of_five_defaults(const base_of_five_defaults&) = default;

是的。 声明 1 个默认用户声明的构造函数。base_of_five_defaults(base_of_five_defaults&&) = default;

使编译器生成此类构造函数的定义,但它已由用户声明。= default

C++标准没有提供用户声明的明确定义,因此英语的意思是“由用户声明”。

这就是咬你的地方:[class.default.ctor]/1

[class.default.ctor]/1

类 X 的默认构造函数是类 X 的构造函数,其中每个不是函数参数包的参数都有一个默认参数(包括没有参数的构造函数的情况)。
如果类 X 没有用户声明的构造函数,则没有参数的非显式构造函数将隐式声明为默认值 ([dcl.fct.def])。
隐式声明的默认构造函数是其类的内联公共成员。


1)不管它是带参数还是不带参数的构造函数,请参阅 的措辞。[class.default.ctor]/1