#include <iostream>
#include <string>
using namespace std;
string&& f(string&& rvf)
{
cout << rvf << endl;
return (string&&)rvf;
// in the return statement, how rvf has become an lvalue?
// because of this I had to typecast explicitly
}
string&& g()
{
return "xyz";
}
int main()
{
string&& st = f("rvalue");
cout << "f " << st << endl;
string&& st2 = g();
cout << "g " << str2 << endl;
// why this line prints junk / crashes some times?
return 0;
}
一般问题:
当我们将rvalue分配给普通变量时,如何进行复制?右移值是如何&#34;移动&#34;进入另一个变量?
复制后rvalue会发生什么?会立即销毁还是超出范围?
答案 0 :(得分:2)
// in the return statement, how rvf has become an lvalue?
虽然rvf
的类型是std::string
的右值引用,但rvf
本身是左值。以这种方式思考:rvf
是一个命名变量,你可以取其地址;你可以非常肯定这是一个左值。
// why this line prints junk / crashes some times?
因为您在g
中有未定义的行为:
string&& g()
{
return "xyz";
}
构造一个临时的std::string
,然后返回对它的引用。无论这是左值还是右值引用,一旦你阅读它,你就会陷入未定义行为的漏洞。
当我们将rvalue分配给普通变量时,如何进行复制?右移值是如何&#34;移动&#34;进入另一个变量?
这取决于班级。对于内置类型,移动与副本相同。想想你将如何移动&#34; int
;它没有多大意义。对于像std::vector
这样的类,它基本上将指针复制到内部动态分配的缓冲区,然后将其设置为原始的nullptr
(无论如何都是一个可能的实现)。
复制后rvalue会发生什么?会立即销毁还是超出范围?
同样,这取决于班级。标准库类处于&#34;有效但未指定的状态&#34;移动后,他们仍然满足任何阶级不变量,但你不应该依赖任何有用的东西。您可以愉快地编写一个符合标准的类,在移动之后您无法访问,而不会遇到未定义的行为。