std :: move返回和输入引用参数

时间:2016-12-21 14:51:45

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

(A)

std::string doNothing(const std::string&& s)
{
  return std::move(s);
}

(B)

std::string doNothing(const std::string& s)
{
  return std::move(s);
}

(试验)

const std::string str = "aaaaaa";
const auto str2 = doNothing(str);

两个问题:

  1. 是(A)和(B)不同吗?
  2. in(测试):将是不确定的?将它移到str2后?

3 个答案:

答案 0 :(得分:2)

  1. 他们是不同的。在一个案例中,函数只接受类型为const字符串的rvalues ,它不接受左值,因为你不能将左值绑定到右值引用。 B case的函数同时接受rvalues和lvalues,因为你可以将rvalue绑定到const lvalue引用。除非你正在做decltype(参数),否则它们在它们的体内是等价的。
  2. 再次,有std :: string(const std :: string&)复制构造函数,它可以接受rvalue字符串对象(std :: move(s)返回const std :: string&&并且发生复制)。

答案 1 :(得分:2)

std::move将(非常量)右值引用作为参数。因此,您无法将其直接绑定到const任何内容,无论是否为rvalue。因此,在(A)和(B)中,当您调用std::move时,它会生成一个未命名的临时副本并移动它。

因此,str永远不会被移动,并且永远不会受到任何影响。

要在不复制的情况下摆脱const,您需要一个明确的const_cast。如果你这样做了,你就会得到明显的未定义行为。

答案 2 :(得分:-1)

使用给定的测试代码,案例不同,因为A无法编译而B编译。

如果A,右值引用无法绑定到左值。

如果B函数返回字符串的副本。将std::move与const引用一起使用仍然会产生一个const引用。