繁体   English   中英

在右值引用上调用 std::move 会发生什么?

[英]What happens when std::move is called on a rvalue reference?

考虑以下 c++ 程序:

string construct(string&& s) {
    // Passing a r-value reference as an argument to the assignment operator
    string constructed = s;
    return constructed;
}

int main() {
    string original = "Hello";
    string temp1 = construct(std::move(original));

    printf("%s\n", original.c_str()); // Prints "Hello", so original has not changed
    return 0;
}

现在我执行的一个小改动是在 r 值引用参数上调用 std::move :

string constructWithMove(string&& s) {
    // Passing a cast to an r-value reference using r-value reference as an argument.
    string constructed = std::move(s);
    return constructed;
}

int main() {
    string original = "Hello";
    string temp = constructWithMove(std::move(original));

    printf("%s\n", original.c_str()); // Prints "", original is set to the empty string, WHY???
    return 0;
} 

因此,看起来将 r 值引用转换为 r 值引用会引发一些特殊情况。 为什么在第一种情况下原始字符串保留其值但在第二种情况下不保留

在右值引用上调用 std::move 会发生什么?

std::move将参数转换为它返回的右值引用。

std::move(r_value_reference_argument)未定义

不。


 // Prints "", original is set to the empty string, WHY???

这里发生了什么事?

因为std::move的结果是一个 r 值(更具体的 x 值)。 并被传递给std::string的构造函数,它调用移动构造函数。 您正在观察一个被移动的字符串。

请注意,此移动将原始字符串留在未指定的 state 中。 它不能保证是空的,甚至与它以前包含的内容也不相同。 也不保证不为空。


好的,但是为什么在第一种情况下原始字符串不为空?

因为s是左值1 ,因此使用了复制构造函数。 复制构造函数使原始字符串保持不变。

1简单的经验法则:如果它是一个名称,那么它就是一个左值。

// Prints "", original is set to the empty string, WHY???

因为你移动了它。

string constructed = s;

这不会导致移动,因为s不是右值 它是一个右值引用,但不是一个右值。 如果它有名称,则它不是右值。 即使变量的类型是右值引用,由其名称组成的表达式也是左值表达式

string constructed = std::move(s);

这会导致移动,因为std::move(s)是一个右值:它是一个临时的并且它的类型不是左值引用。

程序中没有其他动作( std::move不是动作,而是演员表)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM