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

时间:2018-08-24 06:04:16

标签: c++ c++11 rvalue-reference value-categories

我不能这样做:

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

如果我正确理解,则在初始化右值引用时,也会初始化一个临时变量。因此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有何不同?

2 个答案:

答案 0 :(得分:13)

  

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

他们的value categories不同。请注意,类型和值类别是不同的东西。

q是一个命名变量,它的质量为lvalue,因此它不能绑定到右值引用。

(重点是我的)

  

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

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

  

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

答案 1 :(得分:10)

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

我已经在this answer中解决了类似的问题:关键是q作为表达式是 lvalue ,因为它有一个名称。 std::forward<int>(q)(或等效的std::move(q))是没有名称的表达式,由于它们返回(未命名)rvalue引用,因此它们是xvalues,它是rvalue的子类别,因此可以绑定到右值参考。