【问题标题】:Move constructor not getting called? (C++11)移动构造函数没有被调用? (C++11)
【发布时间】:2014-05-11 13:30:35
【问题描述】:

在下面的示例中,为什么在 fun 内部的 'copy' 构造中不调用 move 构造函数,即使 'fun' 的 'src' 参数明确是右值引用并且仅在该构造中使用?

struct Toy {
    int data;

    Toy(): data(0)
    {
        log("Constructed");
    }

    Toy(Toy const& src): data(src.data)
    {
        log("Copy-constructed");
    }

    Toy(Toy&& src): data(src.data)
    {
        log("Move-constructed");
    }
};

Toy fun(Toy&& src)
{
    Toy copy(src);
    copy.data = 777;
    return copy;
}

Toy toy(fun(Toy())); // LOG: Constructed Copy-constructed

【问题讨论】:

  • 顺便说一句,您的示例既不完整也不可用,下次发布其他人可以使用的内容,而不仅仅是随机的 sn-ps,似乎可以从您的预期中复制您的问题。
  • 我不明白复制省略或返回值优化与函数内部构造“复制”对象的方式有什么关系。发生的事情显然是违反直觉和适得其反的。
  • 代码注释表明永远不会调用移动构造函数。该问题提到“src”参数是一个右值引用并用于在“fun”中构造“复制”对象,我认为这足以让这里的聪明人理解我期望移动构造发生的位置。 -_-

标签: c++11 move-constructor


【解决方案1】:

虽然Bob && b 是一个右值引用,但所有在构造后命名的数据使用都将其用作左值。

所以Bob&& b 只会绑定到右值,但是当你使用它时它会不会移动。

获得右值引用的唯一方法是:

  • 没有名称的值,例如临时返回值或强制转换的结果。

  • 在简单的return x; 语句中使用局部值变量。

  • 显式转换为右值,例如使用std::movestd::forward

这可以防止数据从一行静默移动,然后在下一行使用。在使用时将右值视为“我程序员说在这个表达式之后不需要这个”,并且在函数参数中“只取之后不需要的东西”会有所帮助。上面的临时/​​返回异常是编译器可以相对安全地保证这一点的两个地方。

最后,请注意通用引用(auto&&T&&)看起来像右值引用,但有时不是。

【讨论】:

  • 我不太明白... Toy() 传递给 fun 是一个没有名称的值,fun 将其识别为“之后不需要的东西”,事实上,它是除了构造另一个对象之外从未使用过,那为什么编译器不能执行移动呢?
  • @user3026691 在方法中它有一个名字 - src - 所以它是一个使用的左值。它没有被强制转换为右值,也不是在return x; 中使用的局部值,因此很明显它在使用时是一个左值。编译器遵循 C++11 的规则,即“左值”。要修复,std::move。我不打算讨论为什么 C++11 在这种情况下说“左值”,因为它与你的问题无关。
猜你喜欢
  • 2018-06-01
  • 2016-07-12
  • 2018-01-23
  • 2012-05-11
  • 2012-10-17
  • 1970-01-01
  • 2021-08-06
相关资源
最近更新 更多