C++0x 中的特殊成员函数

发布于 2024-09-10 07:34:25 字数 294 浏览 10 评论 0原文

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

我想更新该条目,但我不确定 0x 标准的内容。

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


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

The Wikipedia article about special member functions doesn't contain any reference to move constructors and move assignment operators.

I would like to update the entry but I'm not sure what the 0x standard says.

What are the rules regarding these two functions? Are they automatically generated by the compiler and if so when?


Edit: I've updated the Wikipedia page, if anyone feels like it please help the community by editing it into shape (if needed).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

影子是时光的心 2024-09-17 07:34:25

请记住,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&const volatile B&,并且
  • 对于 X 中属于类类型 M(或其数组)的所有非静态数据成员,每个此类类类型都有一个复制构造函数,其第一个参数的类型为 const M&const volatile M&

否则,隐式声明的复制构造函数将采用 X::X(X&) 形式。

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

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

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

类 X 的隐式声明移动构造函数的形式为 X::X(X&&)

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

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

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

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

然后,§12.8/19 执行与 §12.8/8 相同的操作,但复制赋值和移动赋值运算符除外。它们非常相似,无需在此引用。

为了获得更完整的了解,您需要完整阅读这些部分,但这就是总体思路。我很高兴我们获得了隐式移动语义。


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

Keeping in mind C++0x isn't quite standard yet, this is subject to change. From the FCD (PDF link), move constructors and move assignment operators can indeed be explicitly defaulted, and even implicitly defaulted.*****


I'm just going to quote (heavily abridged) a bunch of stuff that might be useful to glance at:

On explicitly-defaulted functions, §8.4.2/1-2:

A function that is explicitly defaulted shall

  • be a special member function,
  • have the same declared function type as if it had been implicitly declared,
  • not have default arguments, and
  • not have an exception-specification.

If it is explicitly defaulted on its first declaration,

  • it shall be public,
  • it shall not be explicit,
  • it shall not be virtual,
  • it is implicitly considered to have the same exception-specification as if it had been implicitly declared (15.4), and
  • in the case of a copy constructor, move constructor, copy assignment operator, or move assignment operator, it shall have the same parameter type as if it had been implicitly declared.

On special member functions, §12/1:

The default constructor (12.1), copy constructor and copy assignment operator (12.8), move constructor and move assignment operator (12.8), and destructor (12.4) are special member functions. [ Note: The implementation will implicitly declare these member functions for some class types when the program does not explicitly declare them. The implementation will implicitly define them if they are used. See 12.1, 12.4
and 12.8. —end note ]

About implicitly declared functions, §12.8/8-11:

If the class definition does not explicitly declare a copy constructor and there is no user-declared move constructor, a copy constructor is implicitly declared as defaulted (8.4).

The implicitly-declared copy constructor for a class X will have the form X::X(const X&) if

  • each direct or virtual base class B of X has a copy constructor whose first parameter is of type const B& or const volatile B&, and
  • for all the non-static data members of X that are of a class type M (or array thereof), each such class type has a copy constructor whose first parameter is of type const M& or const volatile M&.

Otherwise, the implicitly-declared copy constructor will have the form X::X(X&).

If the class definition does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if

  • X does not have a user-declared copy constructor and
  • the move constructor would not be implicitly defined as deleted.

[ Note: When the move constructor is not implicitly declared or explicitly supplied, expressions that otherwise would have invoked the move constructor may instead invoke a copy constructor. —end note ]

The implicitly-declared move constructor for class X will have the form X::X(X&&).

On implicitly deleted default functions, §12.8/12:

An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy-/move constructor for a class X is defined as deleted (8.4.3) if X has:

  • a variant member with a non-trivial corresponding constructor and X is a union-like class,
  • a non-static data member of class type M (or array thereof) that cannot be copied/moved because overload resolution (13.3), as applied to M’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor, or
  • a direct or virtual base class B that cannot be copied/moved because overload resolution (13.3), as applied to B’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor, or
  • for the move constructor, a non-static data member or direct or virtual base class with a type that does not have a move constructor and is not trivially copyable.

§12.8/13-18 defines how the functions should work when they are implicitly generated.

§12.8/19 then does the same thing as §12.8/8 did, except with the copy-assignment and move-assignment operators. They are similar enough not to warrant quoting here.

For a more complete picture, you'll want to read those sections in their entirety, but that's the general idea. I'm glad we get implicit move semantics.


*But like defaulted copy-functions, they might not always have the correct behavior! The Big Three should become The Big Five. (For example, The Big Three are implemented whenever we need to deep-copy something. We also need to make sure we do a "deep-move", where the source's data is nulled/reset. This is not done implicitly.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文