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

Mat*_*att 16 c++ move-semantics c++11

所以,这提供了预期的输出:

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;
}
Run Code Online (Sandbox Code Playgroud)

字符串加上额外的

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

How*_*ant 18

这是有效的,而不是UB.

它也是可怕的混淆代码. std::move(s)只不过是对左撇子的阉割.它本身实际上根本不生成任何代码.它的唯一目的是将左值转换为右值,以便客户端代码可以在lvalue/rvalue表达式(string在本例中为)上重载.

对于这种情况,你应该通过lvalue-reference传递:

void f(std::string& s)
{
   s += " plus extra";
}
...
f( str );
Run Code Online (Sandbox Code Playgroud)

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

std::string f(std::string s)
{
   s += " plus extra";
   return s;
}
...
str = f( std::move(str) );
Run Code Online (Sandbox Code Playgroud)


ser*_*gej 10

std::move什么都不动.它表示通过将其参数转换为右值,可以" 移动 " 对象.

您的代码有效,并且没有执行移动操作.

如果你移动构造另一个字符串对象,你将得到str调用后未指定状态的行为.move-constructor执行实际的移动操作.f()s

例:

std::vector<std::string> sv;

void f(std::string&& s)
{
    s += " plus extra";
    sv.push_back(std::move(s));         // move s (str) into a new object
}

int main(void)
{
   std::string str = "A string";
   f(std::move(str));                 
   std::cout << str << std::endl;       // output: empty string
   std::cout << sv.back() << std::endl; // output: "A string plus extra"

   return 0;
}
Run Code Online (Sandbox Code Playgroud)


das*_*ght 9

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

string f(std::string&& s) {
    std::string res(std::move(s));
    res += " plus extra";
    return res;
}
Run Code Online (Sandbox Code Playgroud)

str此调用之后的状态有效,但未指定.这意味着您仍然可以分配一个新值以str将其重新置于有效状态,但如果不调用未指定的行为(演示),您将无法输出它.有关移动状态的详细信息,请参阅此问答.