我无法理解右值引用的工作原理。我有以下代码:
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)?
类型和值类别是两个不同的东西。
(强调我的)
每个 C++ 表达式(带有操作数的运算符、文字、变量名称等)都具有两个独立的属性:类型和值类别。
作为命名变量,r是一个左值,它不能绑定到右值引用。
(强调我的)
以下表达式是左值表达式:
- 变量、函数、模板参数对象(C++20 起)或数据成员的名称,与类型无关,例如
std::cin或std::endl。即使变量的类型是右值引用,由其名称组成的表达式也是左值表达式;
另一方面,std::move(r)是一个xvalue,它是一种右值,可以绑定到右值引用。
以下表达式是 xvalue 表达式:
- 函数调用或重载运算符表达式,其返回类型是对对象的右值引用,例如
std::move(x);
关于你的疑惑,
这是因为在
f(r)调用中r被视为左值吗?如果是,是什么类型的std::move(r)?
是的,r是一个左值表达式,并且std::move(r)是一个xvalue(右值)表达式;甚至这两种类型都是右值引用,即int&&.