【问题标题】:C++11 , move constructor requiring to call std::move explicitelyC++11,移动构造函数需要显式调用 std::move
【发布时间】:2015-03-21 00:36:18
【问题描述】:

案例1:我正在写一个简单的移动构造函数:

ReaderValue::ReaderValue(ReaderValue && other)
{
    moveAlloc(other);
}

ReaderValue 类中的moveAlloc 函数原型为:

void moveAlloc(ReaderValue && other);

我从 gcc 4.8 得到错误:

cannot bind 'ReaderValue' lvalue to 'ReaderValue&&'

所以我需要明确地调用它才能编译:

moveAlloc(std::move(other));

案例 2:现在 ReaderValue 有一个 std::string stringData 成员

我再做一个构造函数:

ReaderValue(std::string && otherString)
 : stringData(otherString)
{
}

这行得通,我不需要 std::move 将 otherString 传递给 stringData 构造函数

问题:在第一种情况下,我需要显式调用 std::move 以将右值传递给函数的根本原因是什么?错误消息说 other 是左值,而它看起来确实像右值引用。为什么不是第二种情况?

(请不要回复实际的实现,或者我为什么需要这样做,等等等等……这只是一个基本的语言问题)

【问题讨论】:

  • 也许你需要 std::forward 你的other 而不是移动?
  • 使用forward和move here有什么不同吗?

标签: c++11 constructor move rvalue-reference


【解决方案1】:
ReaderValue::ReaderValue(ReaderValue && other)
{
    //other here is a lvalue(has a name) referring to a rvalue
    //move alloc however takes a rvalue
    moveAlloc(other);
}

这就是为什么你必须明确地将左值转换为右值

moveAlloc(std::move(other)); //other now is a rvalue

请注意,所有 std::move 实际上都是对右值的强制转换。

在带有字符串的第二个示例中:

 ReaderValue(std::string && otherString)
 : stringData(otherString)
{ }

来电

std::string(const string& other);

有效地复制字符串,而:

ReaderValue(std::string && otherString)
: stringData(std::move(otherString))
{ }

来电:

std::string(string&& other);

移动你的字符串

【讨论】:

  • 你的意思是在你帖子的倒数第二个sn-p中写: stringData(std::move(otherString))
【解决方案2】:

建议您阅读此http://thbecker.net/articles/rvalue_references/section_05.html 它会告诉你原因。

简而言之,c++将ReaderValue中的参数other视为左值,但moveAlloc中的参数other是右值。因此,当您调用moveAlloc 时,您必须将ReaderValue 中的other 转换为右值。

【讨论】:

  • 但是在第二种情况下,它是否也会将otherString 视为左值,并为std::string 调用复制构造函数?
  • 是的,有什么问题吗?
  • 是的,我想调用move构造函数来提高效率
猜你喜欢
  • 1970-01-01
  • 2015-02-14
  • 2014-03-13
  • 2013-01-22
  • 1970-01-01
  • 1970-01-01
  • 2014-04-15
  • 1970-01-01
  • 2018-01-23
相关资源
最近更新 更多