这是困扰我的代码
#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()
中调用testRef( int && param )
时,我认为就参数而言,右值引用比右值函数要调用(是的,将发生永恒递归)。但是左值函数被调用。为什么?
答案 0 :(得分:3)
以这种方式考虑,您在std::forward<T>
中使用了func
,因此,要确保将参数作为Rvalue引用转发,您必须在递归函数中执行相同的操作:< / p>
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表达式(也被归类为rvalue表达式。)xvalue表达式绑定到rvalue参考参数。
这可以通过查看Clang's syntax tree的以下功能来看到:
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表达式)时,它就是一个左值。