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

时间:2011-02-09 11:01:30

标签: c++ copy-constructor default-constructor move-constructor move-assignment-operator

我希望在编译器通常自动生成默认构造函数,复制构造函数和赋值运算符的条件下刷新内存。

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

3 个答案:

答案 0 :(得分:125)

在下文中,“自动生成”表示“隐式声明为默认,但未定义为已删除”。在某些情况下,会声明特殊成员函数,但会将其定义为已删除。

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

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

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

答案 1 :(得分:77)

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

C++ rules for automatic constructors and assignment operators 来自Sticky Bits - Becoming a Rule of Zero Hero

答案 2 :(得分:1)

C ++ 17 N4659标准草案

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

当然可以从标准中获得相同的信息。例如。在C++17 N4659 standard draft上:

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

  

6如果类定义未显式声明一个副本构造函数,则将隐式声明一个非显式的构造函数。   如果类定义声明了move构造函数或move赋值运算符,则隐式声明的副本   构造函数定义为删除;否则,将其定义为默认值(11.4)。如果以下情况不建议使用后一种情况   该类具有一个用户声明的副本分配运算符或一个用户声明的析构函数。

对于移动构造函数:

  

8如果类X的定义未显式声明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“析构函数”表示析构函数:

  

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