自动生成 default/copy/move ctor 和 copy/move 赋值运算符的条件?

我想重温一下编译器通常自动生成缺省构造函数、复制建构子和赋值运算符的条件。

我记得有一些规则,但我不记得了,也找不到一个有信誉的资源在线。有人能帮忙吗?

41792 次浏览

在下文中,“自动生成”意味着“隐式声明为默认,但不定义为删除”。在某些情况下,声明了特殊成员函数,但将其定义为删除。

  • 如果没有用户声明的构造函数(12.1/5) ,缺省构造函数会自动生成。
  • 如果没有用户声明的 move 构造函数或 move 赋值操作符(因为在 C + + 03中没有 move 构造函数或 move 赋值操作符,所以在 C + + 03中简化为“ always”) ,复制建构子就会自动生成(12.8/8)。
  • 如果没有用户声明的 move 构造函数或 move 赋值运算符(12.8/19) ,则自动生成拷贝赋值运算符。
  • 如果没有用户声明的析构函数(12.4/4) ,则自动生成析构函数。

C + + 11及更高版本:

  • 如果没有用户声明的复制建构子、复制赋值操作符或析构函数,并且生成的 move 构造函数有效(12.8/10) ,move 构造函数就会自动生成。
  • 如果没有用户声明的复制建构子、拷贝赋值操作符或析构函数,并且所生成的 move 赋值操作符是有效的(例如,如果它不需要赋值常量成员) ,那么 move 赋值操作符是自动生成的(12.8/21)。

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

C++ rules for automatic constructors and assignment operators 来自: 《粘性比特-成为零英雄规则》

C + + 17 N4659标准草案

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

当然,同样的信息也可以从标准中获得,例如 C + + 17 N4659标准草案:

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

如果类定义没有显式地声明一个复制建构子,那么就会隐式地声明一个非显式的。 如果类定义声明了 move 构造函数或 move 赋值运算符,则隐式声明的副本 构造函数被定义为已删除; 否则,它被定义为缺省值(11.4) 该类具有用户声明的复制赋值运算符或用户声明的析构函数。

以及 move 构造函数:

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

  • (8.1) ー X 没有用户声明的复制建构子,

  • (8.2) ー X 没有用户声明的拷贝赋值操作符

  • (8.3) ー X 没有用户声明的移动赋值操作符,并且

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

15.8.2“复制/移动赋值操作符”表示复制赋值:

2如果类定义没有显式声明复制赋值运算符,则隐式声明复制赋值运算符。 如果类定义声明了 move 构造函数或 move 赋值运算符,则隐式声明的 拷贝赋值操作符被定义为已删除; 否则,它被定义为默认值(11.4) 如果类具有用户声明的复制建构子或用户声明的析构函数,则不推荐使用 case。

以及移动任务:

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

  • (4.1)ー X 没有使用者声明的复制建构子
  • (4.2)ー X 没有用户声明的 move 构造函数,
  • (4.3)ー X 没有用户声明的复制赋值操作符,以及
  • (4.4)ー X 没有用户声明的析构函数。

15.4“析构函数”指的是析构函数:

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