C++通用参考.为什么右值引用变为右值?
C++ universal references. Why rvalue reference becomes lvalue?
这是困扰我的代码
#include <iostream>
#include "DataItem.h"
void testRef( const int & param )
{
std::cout << "Lvalue reference" << std::endl;
}
void testRef( int && param )
{
std::cout << "Rvalue reference" << std::endl;
// Here's the thing I can't get. Why param is lvalue reference here??
testRef( param );
}
template<class T>
void func( T && param )
{
testRef( std::forward<T>( param ) );
}
int main2()
{
int a = 12;
func( a );
std::cout << "=================" << std::endl;
func( 14 );
std::cout << "=================" << std::endl;
return 0;
}
当我在testRef( int && param )
中调用testRef()
时,我假设只要参数是右值引用,那么将调用 ravalue 函数(是的,会发生永恒递归)。但是调用了左值函数。为什么?
这样想,你在func
中使用了std::forward<T>
,所以同样,为了确保参数作为 Rvalue 引用转发,你必须在递归函数中做同样的事情:
void testRef(int && param)
{
std::cout << "Rvalue reference" << std::endl;
// Here's the thing I can't get. Why param is lvalue reference here??
testRef( param );
testRef(std::forward<int &&>(param)); // now it will stay an Rvalue reference
testRef(std::move(param)); // make it an Rvalue reference
}
我们需要std::forward
或std::move
的原因是param
属于int&&
类型,它是一个左值(即右值引用参数在使用它时是一个左值表达式)。
在后台,这些模板最终将执行一个static_cast<int &&>
,从而生成一个 xvalue 表达式(也称为右值表达式)。xvalue 表达式绑定到右值引用参数。
这可以通过查看以下函数的 Clang 语法树来看到:
rvalue reference parameter (which binds to rvalue expressions)
vvvvvvvvvvv
void testRef(int&& param)
{
//std::move(param);
lvalue expression of type int&&
vvvvv
static_cast<int &&>(param);
^^^^^^^^^^^^^^^^^^^^^^^^^^
xvalue expression
(considered an rvalue expression which binds to rvalue reference parameters)
}
上述函数的抽象语法树:
TranslationUnitDecl
`-FunctionDecl <line:3:1, line:7:1> line:3:6 testRef 'void (int &&)'
|-ParmVarDecl <col:14, col:21> col:21 used param 'int &&'
`-CompoundStmt <line:4:1, line:7:1>
`-CXXStaticCastExpr <line:6:5, col:30> 'int' xvalue static_cast<int &&> <NoOp>
`-DeclRefExpr <col:25> 'int' lvalue ParmVar 0x55a692bb0a90 'param' 'int &&'
解释引用参数成为左值的简略方法是说,当它有一个名称(id-expression)时,它是一个左值。
相关文章:
- 将对象数组的引用传递给函数
- 什么时候在C++中返回常量引用是个好主意
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 何时在引用或唯一指针上使用移动语义
- 如何在c++中使用引用实现类似python的行为
- 编译C++时未定义的引用
- 是否可以通过引用通过参数返回参考
- 传递对variadic-templates的引用使用std ::参考 - wrapper
- 参考和指针的右引用
- C++通用参考.为什么右值引用变为右值?
- 通过参考const成员通过参考时,尝试引用已删除的函数
- 如果铸造运算符对类型和引用类型的引用,为什么直接列表初始化会导致类型参考铸件的模棱两可
- 为什么const/nonconst lvalue引用与rvalue参考结合
- rvalue引用lVALUE参考-UB
- 将参考引用到未知长度的阵列而不是指针是优雅的吗?
- C 禁止将铸件引用到RVALUE参考
- 对[class::function]的未定义引用/对[class]的typeinfo的未定义参考
- 在论文中引用/参考OpenMP
- 我们可以将规范性参考文献中未明确引用的内容应用到C++标准中吗
- 左值参考的右值参考与左值/右值的右值引用