如果我将一个本地对象移动到一个函数中,它之后是否仍然有效?

时间:2016-03-25 18:51:41

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

因此,这提供了预期的输出:

void f(std::string&& s)
{
   s += " plus extra";
}

int main(void)
{
   std::string str = "A string";
   f( std::move(str) );
   std::cout << str << std::endl;

   return 0;
}
  
    

字符串加上额外的

  

也就是说,当我在Ideone上运行它时,它可以工作,但它是UB吗?在调用f之前和之后添加额外的字符串初始化并没有改变任何东西。

4 个答案:

答案 0 :(得分:18)

这是有效的,而不是UB。

它也是可怕的混淆代码。 std::move(s)只不过是对右值的强制转换。它本身并不实际生成任何代码。它的唯一目的是将左值转换为右值,以便客户端代码可以重载lvalue / rvalue表达式(在这种情况下为string)。

对于这种情况,你应该通过左值引用:

void f(std::string& s)
{
   s += " plus extra";
}
...
f( str );

或者,传递值并返回一个新字符串:

std::string f(std::string s)
{
   s += " plus extra";
   return s;
}
...
str = f( std::move(str) );

答案 1 :(得分:10)

ruamel.yaml无法移动任何内容。它表示某个对象可能是<#34; &#34;移动它的参数是 rvalue

您的代码有效且没有执行移动操作。

如果你从std::move 移动构造另一个字符串对象,那么在调用str之后,你会得到f()状态未指定的行为。 move-constructor执行实际的移动操作。

示例:

s

答案 2 :(得分:9)

代码有效,因为没有执行实际移动。以下是如何使其无效:

string f(std::string&& s) {
    std::string res(std::move(s));
    res += " plus extra";
    return res;
}

此次调用后str的状态有效,但未指定。这意味着您仍然可以为str分配一个新值以使其恢复到有效状态,但是您无法在不调用未指定的行为(demo)的情况下输出它。有关移出状态的具体信息,请参阅this Q&A

答案 3 :(得分:3)

std::move只是将您的对象转换为右值引用。由于您的函数需要引用并且只是对它执行某些操作,因此此处不会使用所有权,因此您的字符串仍处于有效状态并且可以安全使用。

我不建议在您的代码中使用它,因为它会产生误导,因为很多人会认为您的字符串无效,因为取得所有权是rvalue引用的主要用途,因此std::move

如果您真的需要以这种方式调用此函数,我建议您写一下:

std::string myString{"a string"};

// leave a comment here to explain what you are doing.
f(static_cast<std::string&&>(myString));

但请注意,如果函数f取值而不是引用,那么您的示例会有所不同。在这种情况下,使用std::movestatic_cast调用它会使字符串无效。