142

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

我记得有一些规则,但我不记得了,也找不到网上有信誉的资源。任何人都可以帮忙吗?

4

3 回答 3

146

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

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

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

  • 如果没有用户声明的复制构造函数、复制赋值运算符或析构函数,并且生成的移动构造函数有效(第 12.8/10 节),则会自动生成移动构造函数。
  • 如果没有用户声明的复制构造函数、复制赋值运算符或析构函数,并且生成的移动赋值运算符有效(例如,如果它不需要分配常量成员)(第 12.8 节/ 21)。
于 2011-02-09T11:17:46.320 回答
120

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

自动构造函数和赋值运算符的 C++ 规则 来自Sticky Bits - 成为零英雄的规则

于 2016-07-08T01:02:31.820 回答
4

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)。如果类具有用户声明的复制构造函数或用户声明的析构函数,则不推荐使用后一种情况。

对于移动分配:

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

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

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

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

于 2018-11-15T09:09:45.633 回答