C++ - 将右值引用传递给函数?

Mar*_*tin 4 c++

我无法理解右值引用的工作原理。我有以下代码:

void f(int&& i)
{}

int main()
{
    int i = 42;
    int&& r = std::move(i);

    f(r);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在这里,我收到以下编译器错误:

prog.cpp: In function ‘int main()’:
prog.cpp:46:7: error: cannot bind rvalue reference of type ‘int&&’ to lvalue of type ‘int’
     f(r);
       ^
prog.cpp:38:6: note:   initializing argument 1 of ‘void f(int&&)’
 void f(int&& i)
      ^
Run Code Online (Sandbox Code Playgroud)

当我显式声明r为右值引用时,为什么编译器认为我正在传递左值?这样做f(std::move(r))似乎有效,但我仍然不明白那里有什么不同。

这是因为在f(r)调用中r被视为左值吗?如果是,是什么类型的std::move(r)

son*_*yao 6

类型和值类别是两个不同的东西。

(强调我的)

每个 C++ 表达式(带有操作数的运算符、文字、变量名称等)都具有两个独立的属性:类型和值类别

作为命名变量,r是一个左值,它不能绑定到右值引用。

(强调我的)

以下表达式是左值表达式:

  • 变量、函数、模板参数对象(C++20 起)或数据成员的名称,与类型无关,例如std::cinstd::endl即使变量的类型是右值引用,由其名称组成的表达式也是左值表达式

另一方面,std::move(r)是一个xvalue,它是一种右值,可以绑定到右值引用。

以下表达式是 xvalue 表达式:

  • 函数调用或重载运算符表达式,其返回类型是对对象的右值引用,例如std::move(x);

关于你的疑惑,

这是因为在f(r)调用中r被视为左值吗?如果是,是什么类型的std::move(r)

是的,r是一个左值表达式,并且std::move(r)是一个xvalue(右值)表达式;甚至这两种类型都是右值引用,即int&&.

  • @Martin 这是相当 C++ 风格的思维...;) (2认同)