【问题标题】:Why when user provides move constructor or move assignment, copy constructor and copy assignment will be deleted?为什么当用户提供移动构造函数或移动赋值时,复制构造函数和复制赋值会被删除?
【发布时间】:2016-09-10 11:52:55
【问题描述】:

我在看CppCon2014, Michael Caisse, The Canonical Class talk, 在 28'31",他展示了一个图表,显示了当用户提供一些复制控制时,编译器将如何隐式提供或不提供其余部分:

我不太了解带有“删除”的单元格——似乎标准说,当用户提供移动构造函数或移动赋值时,复制构造函数和复制赋值将被删除——好的,但为什么呢?

让我们更具体一点。

第一季度。当用户提供移动构造函数时,复制构造函数和复制构造函数将被删除 - 这是为了避免错误使用,为构造函数或赋值提供左值,左值变得无效?这是要显式强制将参数传递给构造函数或赋值为右值吗?

第二季度。当用户提供移动分配时,复制分配将被删除-这与Q1相同吗?

第三季度。当用户提供移动赋值时,复制构造函数将被删除—— 为什么这样?移动赋值似乎不会与复制构造函数混淆?

【问题讨论】:

    标签: c++ constructor move


    【解决方案1】:

    考虑到一些不幸的历史,这是最不安全的方式。

    用户定义析构函数只有一个原因,那就是我们正在管理一个本身不是 RAII 的资源。如果我们正在管理一个资源,它就不会很好地复制自己(或移动自己)。这些操作需要手动管理。

    如果我们提供析构函数,语言真的应该隐式删除复制和移动操作符。不幸的是,这在早期是没有预见到的,所以我们有规则 3——“如果你定义了析构函数,你必须定义一个拷贝构造函数和拷贝赋值”。

    这条规则是为了让我们远离语言的陷阱。

    有一个关闭这个漏洞 (IIRC) 的提议,据我记得,它被拒绝了,因为它会破坏太多现有代码(尽管坦率地说,所有这些现有代码都是危险的错误,这本来是没有坏事)。

    所以我们在哪里。原则是,如果您手动管理资源,则必须在所有 5 个操作中管理它。如果您手动编写其中一项操作,则需要全部编写。

    只是为了自动删除复制构造函数/复制分配,语言仍然被破坏。

    答案当然是永远不要手动管理资源。由于我们有带有自定义删除器的智能指针,可以为我们管理资源,我们很少需要这样做。当我们这样做时,我们应用 5、3 的规则......但我们应该总是更喜欢无规则 - 使用托管资源并且不定义任何析构函数、复制、移动或赋值运算符,只需让编译器做正确的事东西。

    【讨论】:

      猜你喜欢
      • 2016-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-22
      • 1970-01-01
      • 2019-09-29
      相关资源
      最近更新 更多