这些右值参考是什么?

时间:2016-10-11 14:36:06

标签: c++ c++11

#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会发生什么?会立即销毁还是超出范围?

1 个答案:

答案 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;移动后,他们仍然满足任何阶级不变量,但你不应该依赖任何有用的东西。您可以愉快地编写一个符合标准的类,在移动之后您无法访问,而不会遇到未定义的行为。