【问题标题】:Deleting move constructor and constructing object from rvalue删除移动构造函数并从右值构造对象
【发布时间】:2019-10-08 01:35:47
【问题描述】:

我试图理解“有效的现代 C++”中关于特殊成员函数生成的第 17 项,所以我尝试了一些示例并试图推理某些行为。书中说:

..当我提到移动构造或移动分配数据成员或基类的移动操作时,不能保证移动会实际发生。实际上,“按成员移动”更像是按成员移动请求,因为不支持移动的类型(即,不提供对移动操作的特殊支持,例如,大多数 C++98 遗留类)将被“移动” ” 通过他们的复制操作。 ... 此外,不会为任何明确声明复制操作的类生成移动操作。

如果我显式删除移动构造函数,则下面的代码会出错,但如果我不这样做,则对象“s1”会在没有任何错误的情况下构造副本。这是指向相同代码的魔杖盒链接:wandbox link。我想我不明白删除移动构造函数和不定义移动构造函数之间的区别。

#include <iostream>

struct S
{
    S() = default;
    S(const S&) {
        std::cout << "Copying" << std::endl;
    }
   // S(S&&) = delete;
};

S return_lvalue() {
    S ret{};
    return ret;
}

int main() {
    std::cout << "Hello world" << std::endl;
    // Error here if I delete move constructor
    S s1 = return_lvalue();
}

【问题讨论】:

    标签: c++ c++11 move move-semantics


    【解决方案1】:

    我想我不明白删除移动构造函数和不定义移动构造函数之间的区别。

    当你这样做时

    struct S
    {
        S() = default;
        S(const S&) {
            std::cout << "Copying" << std::endl;
        }
    };
    

    编译器不会生成移动构造函数。如果你试图移动它,重载解析只会找到S(const S&amp;),你会得到一个副本。与

    struct S
    {
        S() = default;
        S(const S&) {
            std::cout << "Copying" << std::endl;
        }
        S(S&&) = delete;
    };
    

    当您移动S 类型的对象时,重载解析会找到S(const S&amp;)S(S&amp;&amp;),但它会选择S(S&amp;&amp;),因为它是更好的匹配。然后它看到它被删除了,你得到一个错误。

    您需要记住的是,已删除的构造函数不会将它们从类中删除。它声明它们并使它们可用于重载解析,并且只有在重载解析发生后,它才会检查它是否被删除。

    【讨论】:

      【解决方案2】:

      删除一个特殊的成员函数与不声明它是不一样的。这和声明它然后在你使用它时强制编译错误是一样的。

      因此,删除移动 ctor 并没有太多好处……除非您出于某种原因也删除了复制 ctor,但根本不声明移动 ctor。

      这与引用没有太大关系,也就是说,如果您 确实 声明了一个移动 ctor 但没有在其中做任何“移动的事情”,那么最终没有任何价值被感动了,这可能与您的用户的期望相反。

      我建议您不要声明您的移动 ctor。同样,这与删除它不同。并且不会自动生成一个,因为您有一个复制 ctor。

      在此处查找更多技术信息:

      请注意,由于省略,您的程序在两种情况下都在 C++17 模式下编译。

      【讨论】:

      • 引用的位实际上表示如果您不声明移动构造函数,则将调用复制构造函数。此外,由于您提到的原因,我在链接的示例中禁用了复制省略并使用 c++11 进行编译。
      • @MikeSweeney 但是“不要声明移动构造函数”和“将移动构造函数声明为已删除”是两件事:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-13
      • 2021-09-15
      • 2018-03-26
      • 1970-01-01
      • 2013-01-10
      • 1970-01-01
      相关资源
      最近更新 更多