【发布时间】:2020-11-16 05:24:44
【问题描述】:
考虑以下 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 值引用会引发一些特殊情况。 为什么在第一种情况下原始字符串保留了它的值而在第二种情况下没有?
【问题讨论】:
-
现在我执行的一个小更改是在 r 值引用参数上调用 std::move 不,这不是你所做的。您在左值引用参数上调用了 std::move。
-
@Eljay
string&&不是右值引用吗? -
参数通过引用接受一个右值参数。局部参数是命名的,所以不是右值,需要
std::moved作为右值使用。 -
我认为您缺少的一点是,在
string constructed = s;之后,s必须 保持有效并且不能 从中移出。毕竟,下一行代码可能是string constructed2 = s;。但是,在string constructed = std::move(s);中,您已授予从s移动以构造新字符串的权限,因此它可能会将s更改为有效但不同的状态。 -
@eerorika 也许应该改写:你不能在引用类型的参数上调用函数因为没有引用类型的表达式。在
constructWithMove中,表达式s是string类型的左值。std::move使用左值string调用。声明string &&s影响绑定到s的内容(在调用点),但不影响s在函数体内的行为。实际上在右值上调用std::move将是std::move(std::move(s))或类似std::move(std::string(""))。
标签: c++ c++11 move move-semantics rvalue-reference