3

关于特殊成员函数的 Wikipedia 文章不包含对移动构造函数和移动赋值运算符的任何引用。

我想更新条目,但我不确定 0x 标准是怎么说的。

这两个函数的规则是什么?它们是由编译器自动生成的吗?如果是,什么时候生成?


编辑:我已经更新了维基百科页面,如果有人喜欢它,请通过编辑它来帮助社区(如果需要)。

4

1 回答 1

3

请记住,C++0x 还不是很标准,这可能会发生变化。从FCD(PDF 链接)来看,移动构造函数和移动赋值运算符确实可以显式默认,甚至隐式默认。*****


我只是要引用(大量删节)一堆可能有用的东西:

在显式默认函数上,第 8.4.2/1-2 节:

显式默认的函数应

  • 是一个特殊的成员函数,
  • 具有与隐式声明相同的声明函数类型,
  • 没有默认参数,并且
  • 没有异常规范。

如果它在第一个声明中被明确默认,

  • 应该是公开的,
  • 它不应是明确的,
  • 它不应是虚拟的,
  • 它被隐式认为具有与隐式声明(15.4)相同的异常规范,并且
  • 在复制构造函数、移动构造函数、复制赋值运算符或移动赋值运算符的情况下,它应具有与已隐式声明的参数类型相同的参数类型。

关于特殊成员函数,§12/1:

默认构造函数 (12.1)、复制构造函数和复制赋值运算符 (12.8)、移动构造函数和移动赋值运算符 (12.8) 和析构函数 (12.4) 是特殊的成员函数。[注意:当程序没有显式声明它们时,实现会为某些类类型隐式声明这些成员函数。如果使用它们,实现将隐式定义它们。见 12.1、12.4 和 12.8。——尾注]

关于隐式声明的函数,§12.8/8-11:

如果类定义没有显式声明复制构造函数并且没有用户声明的移动构造函数,则复制构造函数被隐式声明为默认值 (8.4)。

类 X 的隐式声明的复制构造函数的形式为X::X(const X&)if

  • X 的每个直接或虚拟基类 B 都有一个复制构造函数,其第一个参数的类型为const B&or const volatile B&,并且
  • 对于 X 的所有属于类类型 M(或其数组)的非静态数据成员,每个此类类型都有一个复制构造函数,其第一个参数的类型为const M&or const volatile M&

否则,隐式声明的复制构造函数将具有X::X(X&).

如果类定义没有显式声明移动构造函数,当且仅当

  • X 没有用户声明的复制构造函数,并且
  • 移动构造函数不会被隐式定义为已删除。

[注意:当移动构造函数没有被隐式声明或显式提供时,否则会调用移动构造函数的表达式可能会调用复制构造函数。——尾注]

类 X 的隐式声明的移动构造函数将具有X::X(X&&).

关于隐式删除的默认函数,§12.8/12:

隐式声明的复制/移动构造函数是其类的内联公共成员。如果 X 具有以下属性,则类 X 的默认复制/移动构造函数被定义为已删除 (8.4.3):

  • 具有非平凡对应构造函数的变体成员,并且 X 是类联合类,
  • 类类型 M(或其数组)的非静态数据成员,因为重载决议 (13.3) 应用于 M 的相应构造函数时,会导致歧义或从默认值中删除或无法访问的函数,因此无法复制/移动构造函数,或
  • 无法复制/移动的直接或虚拟基类 B,因为应用于 B 的相应构造函数的重载解析 (13.3) 会导致歧义或从默认构造函数中删除或无法访问的函数,或
  • 对于移动构造函数,非静态数据成员或直接或虚拟基类,其类型没有移动构造函数且不可轻易复制。

§12.8/13-18 定义了函数在隐式生成时应如何工作。

§12.8/19 然后与 §12.8/8 做同样的事情,除了复制赋值和移动赋值运算符。它们足够相似,不值得在这里引用。

要获得更完整的图片,您需要完整阅读这些部分,但这是大意。我很高兴我们得到了隐式移动语义。


*但就像默认的复制功能一样,它们可能并不总是具有正确的行为!三巨头应该成为五巨头。(例如,当我们需要深度复制某些东西时,就会实现三巨头。我们还需要确保我们执行“深度移动”,其中源的数据被清空/重置。这不是隐式完成的。)

于 2010-07-19T12:48:24.757 回答