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

oom*_*pah 121 c++ copy-constructor default-constructor move-constructor move-assignment-operator

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

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

Phi*_*ipp 128

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

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

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

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

  • 我想你应该提一下,在类中使用`const`成员会阻止构造函数被自动生成... (9认同)
  • 继承的析构函数是否有效?我的意思是,说我有一个带有空虚拟析构函数的基类.它是否会阻止在子类中创建移动构造函数?如果答案是肯定的,那么如果我在基类中定义移动构造函数会有帮助吗? (8认同)
  • @约翰恐怕不是。大约是 8 年前我最后一次使用 C++。 (2认同)

Mar*_* M. 88

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

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

  • 复制ctor/assignment彼此"独立".如果只编写一个,编译器将提供另一个.相反,如果您提供移动ctor或移动分配,编译器将不提供另一个. (6认同)
  • @MarcoM,据我所知,“如果你写...”条件包括将特殊成员函数设置为“=删除”(明显)或“=默认”(对我来说不太明显)的两种情况)。我对吗? (2认同)

Cir*_*四事件 9

C++17 N4659 标准草案

\n\n

要快速进行跨标准参考,请查看以下 cppreference 条目的“隐式声明”部分:

\n\n\n\n

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

\n\n

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

\n\n
\n

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

\n
\n\n

对于移动构造函数:

\n\n
\n

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

\n\n
    \n
  • (8.1)\n \xe2\x80\x94 X 没有用户声明的复制构造函数,

  • \n
  • (8.2)\n \xe2\x80\x94 X 没有用户声明的复制赋值运算符,

  • \n
  • (8.3)\n \xe2\x80\x94 X 没有用户声明的移动赋值运算符,并且

  • \n
  • (8.4)\n \xe2\x80\x94 X 没有用户声明的析构函数。

  • \n
\n
\n\n

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

\n\n
\n

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

\n
\n\n

对于移动分配:

\n\n
\n

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

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

15.4“析构函数”对于析构函数是这样说的:

\n\n
\n

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

\n
\n