使用C ++ 11,Rule-of-Three成为Rule-of-Five? [英] Rule-of-Three becomes Rule-of-Five with C++11?

查看:163
本文介绍了使用C ++ 11,Rule-of-Three成为Rule-of-Five?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,在观看这个精彩关于右值引用的讲座,我认为每个类都将受益于这样的移动构造函数, template< class T> MyClass(T& amp; other) 编辑 ,当然还有一个移动赋值运算符, template< class T> ; MyClass&运算符=(T&& amp;其他)作为Philipp指出在他的答案,如果它动态分配成员,或一般存储指针。就像你应该有一个copy-ctor,赋值运算符和析构函数,如果前面提到的点适用。
想法?

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?

推荐答案

我会说三个规则成为三,四和五的规则: / p>

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:


  • 无(对于许多简单的类,隐式生成的特殊成员函数是正确和快速的)

  • 析构函数,复制构造函数,复制赋值运算符(在这种情况下
    类不会移动)

  • 析构函数,移动构造函数,移动赋值运算符(在这种情况下,类不会是可复制的,对于资源管理类,底层资源不可复制是有用的)

  • ,复制赋值运算符,移动构造函数(因为复制elision,没有开销,如果复制赋值运算符以值的形式接受其参数)

  • 析构函数,复制构造函数, ,
    移动赋值运算符

  • None (for many simple classes where the implicitly generated special member functions are correct and fast)
  • Destructor, copy constructor, copy assignment operator (in this case the class will not be movable)
  • Destructor, move constructor, move assignment operator (in this case the class will not be copyable, useful for resource-managing classes where the underlying resource is not copyable)
  • Destructor, copy constructor, copy assignment operator, move constructor (because of copy elision, there is no overhead if the copy assignment operator takes its argument by value)
  • Destructor, copy constructor, copy assignment operator, move constructor, move assignment operator

请注意,移动构造函数和移动赋值运算符不会为明确声明任何其他特殊成员函数的类生成,不会为显式声明move构造函数或move赋值运算符的类生成复制构造函数和复制赋值操作符,并且明确声明析构函数和隐式定义的复制构造函数或隐式定义的复制赋值操作符被视为已弃用。特别是,以下完全有效的C ++ 03多态基类

Note that move constructor and move assignment operator won't be generated for a class that explicitly declares any of the other special member functions, that copy constructor and copy assignment operator won't be generated for a class that explicitly declares a move constructor or move assignment operator, and that a class with a explicitly declared destructor and implicitly defined copy constructor or implicitly defined copy assignment operator is considered deprecated. 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 (automatic generation of all special member functions).

与大三的规则相反,如果不遵守规则会导致严重的损害,没有明确声明移动构造函数和移动赋值运算符一般都很好,但是相对于效率通常次优。如上所述,只有没有明确声明的拷贝构造函数,拷贝赋值运算符或析构函数时,才会生成move constructor和move赋值运算符。这与传统的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中。如果你有一个移动构造函数和移动赋值运算符,专门 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. If you 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,Rule-of-Three成为Rule-of-Five?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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