为了账号安全,请及时绑定邮箱和手机立即绑定

三阶规则与C ++ 11一起成为五次规则?

三阶规则与C ++ 11一起成为五次规则?

C++ C
不负相思意 2019-05-27 11:08:06
三阶规则与C ++ 11一起成为五次规则?因此,在观看了关于右值引用的精彩演讲之后,我认为每个类都会受益于这样的“移动构造函数”,template<class T> MyClass(T&& other) 编辑,当然还有“移动赋值运算符”,template<class T> MyClass& operator=(T&& other)正如Philipp在他的回答中指出的,如果它已经动态分配成员,或通常存储指针。就像你应该有一个copy-ctor,赋值运算符和析构函数,如果之前提到的点适用。思考?
查看完整描述

4 回答

?
慕村225694

TA贡献1880条经验 获得超4个赞

我要说三法则成为三,四,五的规则:

每个类应明确定义以下一组特殊成员函数:

  • 没有

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

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

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

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

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

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

  • 析构函数,复制构造函数,复制赋值运算符,移动构造函数(因为复制省略,如果复制赋值运算符按值获取其参数,则没有开销)

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

请注意,不会为显式声明任何其他特殊成员函数的类生成移动构造函数和移动赋值运算符,不会为显式声明移动构造函数或移动的类生成复制构造函数和复制赋值运算符赋值运算符,并且具有显式声明的析构函数和隐式定义的复制构造函数或隐式定义的复制赋值运算符的类被视为已弃用。特别是,以下完全有效的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中实现。如果你有一个移动构造函数和移动赋值运算符,则特殊化std::swap将变得不重要,因为泛型std::swap使用移动构造函数并移动赋值运算符(如果可用),并且应该足够快。


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


查看完整回答
反对 回复 2019-05-27
?
猛跑小猪

TA贡献1858条经验 获得超8个赞

我无法相信没有人与此有关

基本上,文章认为“零法则”。我引用整篇文章是不合适的,但我认为这是重点:

具有自定义析构函数,复制/移动构造函数或复制/移动赋值运算符的类应专门处理所有权。其他类不应该有自定义析构函数,复制/移动构造函数或复制/移动赋值运算符。

这一点是恕我直言的重要:

常见的“包中所有”类包含在标准库中:std::unique_ptrstd::shared_ptr。通过使用自定义删除对象,两者都具有足够的灵活性来管理几乎任何类型的资源。


查看完整回答
反对 回复 2019-05-27
?
慕哥9229398

TA贡献1877条经验 获得超6个赞

我不这么认为,三个规则是一个经验法则,规定实现以下一个但不是全部的类可能是错误的。

  1. 复制构造函数

  2. 分配操作员

  3. 析构函数

但是,省略移动构造函数或移动赋值运算符并不意味着错误。它可能是错过了优化的机会(在大多数情况下),或者移动语义与此类无关,但这不是错误。

尽管在相关时定义移动构造函数可能是最佳实践,但这不是强制性的。在许多情况下,移动构造函数与类(例如std::complex)无关,并且在C ++ 03中行为正确的所有类将继续在C ++ 0x中正常运行,即使它们没有定义移动构造函数。


查看完整回答
反对 回复 2019-05-27
?
MMMHUHU

TA贡献1834条经验 获得超8个赞

是的,我认为为这些类提供移动构造函数会很好,但请记住:

  • 这只是一种优化。

    仅实现一个或两个复制构造函数,赋值运算符或析构函数可能会导致错误,而没有移动构造函数可能会降低性能。

  • 无需修改即可始终应用移动构造函数。

    有些类总是分配它们的指针,因此这些类总是在析构函数中删除它们的指针。在这些情况下,您需要添加额外的检查,以确定其指针是已分配还是已被移走(现在为空)。


查看完整回答
反对 回复 2019-05-27
  • 4 回答
  • 0 关注
  • 599 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信