自动生成默认/复制/移动向量和复制/移动赋值运算符的条件?

问题描述 投票:0回答:4

我想刷新我对编译器通常自动生成默认构造函数、复制构造函数和赋值运算符的条件的记忆。

我记得有一些规则,但我不记得了,也无法在网上找到信誉良好的资源。有人可以帮忙吗?

c++ copy-constructor default-constructor move-constructor move-assignment-operator
4个回答
158
投票

下文中,“自动生成”的意思是“隐式声明为默认,但未定义为删除”。在某些情况下,声明了特殊成员函数,但定义为已删除。

  • 如果没有用户声明的构造函数,则自动生成默认构造函数(第 12.1/5 节)。
  • 如果没有用户声明的移动构造函数或移动赋值运算符,则自动生成复制构造函数(因为 C++03 中没有移动构造函数或移动赋值运算符,这在 C++03 中简化为“始终”) (§12.8/8)。
  • 如果没有用户声明的移动构造函数或移动赋值运算符,则自动生成复制赋值运算符(第 12.8/19 节)。
  • 如果没有用户声明的析构函数,则自动生成析构函数(第 12.4/4 节)。

仅限 C++11 及更高版本:

  • 如果没有用户声明的复制构造函数、复制赋值运算符或析构函数,并且生成的移动构造函数有效(第 12.8/10 节),则自动生成移动构造函数。
  • 如果没有用户声明的复制构造函数、复制赋值运算符或析构函数,并且生成的移动赋值运算符有效(例如,如果不需要分配常量成员),则自动生成移动赋值运算符(第 12.8 节) /21).

138
投票

我发现下面的图表非常有用。

来自Sticky Bits - 成为零英雄的规则


8
投票

C++17 N4659 标准草案

如需快速交叉标准参考,请查看以下 cppreference 条目的“隐式声明”部分:

当然可以从标准中获得相同的信息。例如。关于 C++17 N4659 标准草案

15.8.1“复制/移动构造函数”表示复制构造函数:

6 如果类定义没有显式声明复制构造函数,则隐式声明非显式复制构造函数。 如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的副本 构造函数被定义为已删除;否则,它被定义为默认(11.4)。后一种情况将被弃用,如果 该类具有用户声明的复制赋值运算符或用户声明的析构函数。

对于移动构造函数:

8 如果类 X 的定义没有显式声明移动构造函数,则非显式的移动构造函数将被隐式声明 声明为默认当且仅当

  • (8.1) — X 没有用户声明的复制构造函数,

  • (8.2) — X 没有用户声明的复制赋值运算符,

  • (8.3) — X 没有用户声明的移动赋值运算符,并且

  • (8.4) — X 没有用户声明的析构函数。

15.8.2“复制/移动赋值运算符”表示复制赋值:

2 如果类定义没有显式声明复制赋值运算符,则隐式声明一个。 如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的 复制赋值运算符定义为删除;否则,它被定义为默认(11.4)。后者 如果类具有用户声明的复制构造函数或用户声明的析构函数,则不推荐使用 case。

对于移动分配:

4 如果类 X 的定义没有显式声明移动赋值运算符,则将隐式声明 声明为默认当且仅当

  • (4.1) — X 没有用户声明的复制构造函数,
  • (4.2) — X 没有用户声明的移动构造函数,
  • (4.3) — X 没有用户声明的复制赋值运算符,并且
  • (4.4) — X 没有用户声明的析构函数。

15.4“析构函数”为析构函数说:

4 如果类没有用户声明的析构函数,则析构函数将被隐式声明为默认析构函数 (11.4)。一个 隐式声明的析构函数是其类的内联公共成员。


0
投票

Howard Hinnant 的下图很好地总结了所有规则。 红细胞是已弃用的行为,不应依赖。

C++ rules for automatic constructors and assignment operators

来源:Howard Hinnant - 我如何声明我的

class
以及为什么

© www.soinside.com 2019 - 2024. All rights reserved.