在 C++11 中三分法变成五分法? [英] Rule-of-Three becomes Rule-of-Five with C++11?

查看:29
本文介绍了在 C++11 中三分法变成五分法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,看完关于右值引用的精彩讲座,我认为每个类都会从这样的移动构造函数"中受益,templateMyClass(T&& other) edit 当然还有一个移动赋值运算符",template我的课堂&operator=(T&& other) 正如菲利普在他的回答中指出的那样,如果它有动态分配的成员,或者通常存储指针.就像您应该拥有复制构​​造函数、赋值运算符和析构函数一样,如果前面提到的要点适用的话.想法?

So, after watching this wonderful lecture on rvalue references, I thought that every class would benefit of such a "move constructor", template<class T> MyClass(T&& other) edit and of course a "move assignment operator", template<class T> MyClass& operator=(T&& other) as Philipp points out in his answer, if it has dynamically allocated members, or generally stores pointers. Just like you should have a copy-ctor, assignment operator and destructor if the points mentioned before apply. Thoughts?

推荐答案

我想说三法则变成了三四五法则:

I'd say the Rule of Three becomes the Rule of Three, Four and Five:

每个类都应该明确定义一个下面一组特殊成员功能:

Each class should explicitly define exactly one of the following set of special member functions:

  • 析构函数、复制构造函数、复制赋值运算符

此外,每个显式定义析构函数的类都可以显式定义移动构造函数和/或移动赋值运算符.

In addition, each class that explicitly defines a destructor may explicitly define a move constructor and/or a move assignment operator.

通常是以下一组特殊成员函数是明智的:

Usually, one of the following sets of special member functions is sensible:

  • 无(对于隐式生成的特殊成员函数正确且快速的许多简单类)
  • 析构函数、复制构造函数、复制赋值运算符(在这种情况下类将不可移动)
  • 析构函数、移动构造函数、移动赋值运算符(在这种情况下,类将不可复制,对于底层资源不可复制的资源管理类很有用)
  • 析构函数、复制构造函数、复制赋值运算符、移动构造函数(由于复制省略,如果复制赋值运算符按值取参数,则没有开销)
  • 析构函数、复制构造函数、复制赋值运算符、移动构造函数、移动赋值运算符

注意:

  • 不会为显式声明任何其他特殊成员函数(如析构函数、复制构造函数或移动赋值运算符)的类生成移动构造函数和移动赋值运算符.
  • 不会为显式声明移动构造函数或移动赋值运算符的类生成该复制构造函数和复制赋值运算符.
  • 并且具有显式声明的析构函数和隐式定义的复制构造函数或隐式定义的复制赋值运算符的类被视为已弃用.

特别是以下完全有效的 C++03 多态基类:

In particular, the following perfectly valid C++03 polymorphic base class:

class C {
  virtual ~C() { }   // allow subtype polymorphism
};

应改写如下:

class C {
  C(const C&) = default;               // Copy constructor
  C(C&&) = default;                    // Move constructor
  C& operator=(const C&) = default;  // Copy assignment operator
  C& operator=(C&&) = default;       // Move assignment operator
  virtual ~C() { }                     // Destructor
};

有点烦人,但可能比替代方案更好(在这种情况下,自动生成用于复制的特殊成员函数,没有移动的可能性).

A bit annoying, but probably better than the alternative (in this case, automatic generation of special member functions for copying only, without move possibility).

与三巨头规则相反,不遵守规则会造成严重损害,不明确声明移动构造函数和移动赋值运算符通常是好的,但在效率方面通常是次优的.如上所述,移动构造函数和移动赋值运算符仅在没有显式声明的复制构造函数、复制赋值运算符或析构函数时生成.在自动生成复制构造函数和复制赋值运算符方面,这与传统的 C++03 行为不对称,但更安全.因此,定义移动构造函数和移动赋值运算符的可能性非常有用,并创造了新的可能性(纯粹可移动的类),但遵守 C++03 三巨头规则的类仍然可以.

In contrast to the Rule of the Big Three, where failing to adhere to the rule can cause serious damage, not explicitly declaring the move constructor and move assignment operator is generally fine but often suboptimal with respect to efficiency. As mentioned above, move constructor and move assignment operators are only generated if there is no explicitly declared copy constructor, copy assignment operator or destructor. This is not symmetric to the traditional C++03 behavior with respect to auto-generation of copy constructor and copy assignment operator, but is much safer. So the possibility to define move constructors and move assignment operators is very useful and creates new possibilities (purely movable classes), but classes that adhere to the C++03 Rule of the Big Three will still be fine.

对于资源管理类,如果无法复制底层资源,您可以将复制构造函数和复制赋值运算符定义为已删除(这算作定义).通常您仍然需要移动构造函数和移动赋值运算符.复制和移动赋值运算符通常使用 swap 实现,就像在 C++03 中一样.谈swap;如果我们已经有了移动构造函数和移动赋值运算符,专门化std::swap将变得不重要,因为通用 std::swap 使用移动构造函数和移动赋值运算符(如果可用的话)(这应该足够快).

For resource-managing classes you can define the copy constructor and copy assignment operator as deleted (which counts as definition) if the underlying resource cannot be copied. Often you still want move constructor and move assignment operator. Copy and move assignment operators will often be implemented using swap, as in C++03. Talking about swap; if we already have a move-constructor and move-assignment operator, specializing std::swap will become unimportant, because the generic std::swap uses the move-constructor and move-assignment operator if available (and that should be fast enough).

不用于资源管理(即,没有非空析构函数)或子类型多态性(即,没有虚拟析构函数)的类不应声明五个特殊成员函数中的任何一个;它们都将自动生成并且行为正确且快速.

Classes that are not meant for resource management (i.e., no non-empty destructor) or subtype polymorphism (i.e., no virtual destructor) should declare none of the five special member functions; they will all be auto-generated and behave correct and fast.

这篇关于在 C++11 中三分法变成五分法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆