普通的右值引用和 std::forward 返回的引用有什么区别?

What's the difference between an ordinary rvalue reference and one returned by std::forward?

本文关键字:引用 返回 什么 区别 forward std      更新时间:2023-10-16

我不能这样做:

int &&q = 7;
int &&r = q; 
//Error Message:
//cannot convert from 'int' to 'int &&'
//You cannot bind an lvalue to an rvalue reference

如果我理解正确,在初始化 rvalue 引用时,也初始化了一个临时变量。因此,int &&q = 7;可以被视为:

int temp = 7;
int &&q = temp;

当使用右侧的参考时,我实际上是在使用裁判。因此int &&r = q;可以被视为:

int &&r = temp;  //bind an lvalue to an rvalue reference, cause error, understandable

所以以上是我理解编译器错误发生的方式。


为什么添加std::forward可以解决这个问题?

int &&q = 7;
int &&r = std::forward<int>(q);

我知道std::forward总是返回一个右值引用,std::forward返回的引用与int&&q有何不同?

std::forward返回的引用与int&&q有何不同?

它们的价值类别是不同的。请注意,类型和值类别是不同的东西。

q是命名变量,它被限定为左值,因此不能绑定到右值引用。

(强调我的(

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

而从函数返回的右值引用被限定为 xvalue,它属于 rvalue。

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

表达式qstd::forward<int>(q)之间的区别在于前者是左值,而后者是右值(基本类别 xvalue(。

我在这个答案中也谈到了类似的问题:关键是q作为一个表达式是一个左值,因为它有一个名字。std::forward<int>(q)(或等效的std::move(q)(是没有名称的表达式,并且由于它们返回(未命名的(右值引用,因此它们是 x值,它是 rvalue 的子类别,因此可以绑定到右值引用。