c++ - C++11 的三规则变成五规则?

标签 c++ constructor c++11 rvalue-reference rule-of-three

所以,看完this wonderful lecture在右值引用上,我认为每个类都会受益于这样的“移动构造函数”,template<class T> MyClass(T&& other) 编辑,当然还有一个“移动赋值运算符”,template<class T> MyClass& operator=(T&& other)正如菲利普在他的回答中指出的那样,如果它具有动态分配的成员,或者通常存储指针。就像你应该有一个copy-ctor,赋值运算符和析构函数,如果前面提到的点适用的话。 想法?

最佳答案

我会说三法则变成三四五法则:

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

  • None
  • Destructor, copy constructor, copy assignment operator

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:

  • 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

注意:

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

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

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
};

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

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

对于资源管理类,如果无法复制基础资源,您可以将复制构造函数和复制赋值运算符定义为已删除(视为定义)。通常您仍然需要移动构造函数和移动赋值运算符。复制和移动赋值运算符通常使用 swap 实现,如在 C++03 中。谈swap;如果我们已经有一个移动构造函数和移动赋值运算符,specializing std::swap将变得不重要,因为通用 std::swap 使用 move-constructor 和 move-assignment 运算符(如果可用)(并且应该足够快)。

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

关于c++ - C++11 的三规则变成五规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4782757/

相关文章:

c++ - 在生产中使用 GCC 的 C++0x 模式?

c++ - 宏上的用户定义文字运算符

c++ - C++ 编译器如何检测非常量函数体?

c++ - 如何使用 lambda 函数打印一对<>?

go - 包含嵌入的结构 slice 的结构

java - Android自定义arrayadapter构造函数问题

c++ - 按值传递给引用参数

c++ - 使用条件变量在 Linux 中实现 Windows 事件?

c++ - 在 Cython 中包装 C++ 模板函数/方法

c++ - 重写派生类中基类私有(private)成员的行为,C++