rvalue引用成员变量的作用是什么?

7
我在想是否有必要创建一个rvalue引用变量(不作为函数参数)?我理解当rvalue引用作为函数变量时的使用,可以避免不必要的分配等问题。但是,在非函数参数的情况下,是否存在使用rvalue引用变量的用例?最初,我认为这样的变量可以捕获传递的数据以供稍后使用,但是如果我们有一个rvalue引用变量,那么我们已经可以获取其地址,因此它就不能再是rvalue引用了。
我尝试了以下代码,结果(不出所料)无法编译。那么为什么我会想要创建一个rvalue引用变量呢?
void test(int&& a) {}

int&& a(22);
test(a);

谢谢!


1
如果你使用 std::move(a),它就可以编译。 - Quentin
1个回答

5

您的a是一个右值引用的名称。 a本身是一个左值(可以取其地址),类型为右值引用(有点令人困惑)。因此,无论何时将您的a传递给test(a),都会传递一个左值。将左值视为任何具有名称或您可以随后取其地址的对象。您无法将左值绑定到右值引用,因此会出现编译错误

error: cannot bind 'int' lvalue to 'int&&'

您需要传递std::move(a)。在这种情况下,您取消了a的左值特性。

请注意,在函数内部,a也是一个左值(同样,您可以对其执行左值操作,如取其地址等)。每当您希望将其用作右值时,都需要进行转换(std::move)。例如,假设您有一个对象Bar,其中包含成员变量Foo member;,并且您想通过成员函数f移动到它:

void Bar::f(Foo&& param)
{
    member = std::move(param); // need std::move here to move param into member
}

// invoked it as
bar.f(std::move(some_foo)); // move some_foo into param

如果您没有使用 std::moveparam 转换为右值引用,那么您就不会将 param 移动到 member 中,而是只会复制它(如果 param 可以被复制的话,否则会在编译时出错),因为 param 本身是一个左值。希望这样能更清楚明白。

1
好的,这是否意味着,我实际上使用变量'a'捕获了一些rvalue引用- int &&类型显示出这一点,但为了将其用作实际的rvalue引用,我必须手动转换lvalue性质,这是安全的,因为我已经知道它是存储在lvalue变量中的rvalue引用? - bim_bam
@bim_bam 是的,完全正确。而且“工作”只在程序员这一侧进行,编译器执行强制类型转换时没有任何开销。 - vsoftco
@bim_bam 我必须说,我不知道在函数参数之外使用右值引用的好例子,尽管可能有人能想出一个例子。 - vsoftco
“你不能将左值绑定到右值引用”是这个问题的简短答案。 - user2249683
3
当您不再将对象视为lvalue或rvalue时,这个概念就更清晰了。具有值类别的是表达式而不是它们所表示的东西。 - Lightness Races in Orbit
如果有人能够发布另一个答案,那将不胜感激,因为这一个似乎没有提供一个清晰的右值引用变量不是函数参数的示例。 - kingsjester

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接