C++ 通用引用。为什么右值引用变成左值?

标签 c++ rvalue type-deduction

这是困扰我的代码

‍‍‍‍‍#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() 时,我认为只要 param 是右值引用,就会调用 ravalue 函数(是的,永恒会发生递归)。但左值函数被调用。为什么?

最佳答案

这样想吧,你用了std::forward<T>func ,同样,为了确保参数作为右值引用转发,您必须在递归函数中执行相同的操作:

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 表达式绑定(bind)到右值引用参数。

这可以通过查看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 表达式)时,它就是左值。

关于C++ 通用引用。为什么右值引用变成左值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55210225/

相关文章:

c++ - 自动类型推导和 auto&& 与 auto

c++ - 模板库中的名称查找 : why do we add this->

c++ - 当 QWSSERVER::SetCursorVisible(false) 不可见时如何恢复我的鼠标指针?

c++ - 如何以编程方式确定程序是否在用户的 PATH 中

c++ - 从类型 'int&' 的临时类型 'int' 的非常量引用的无效初始化

c++ - 为什么为 T 推导的类型是 const int in void func(T const &t)

具有二进制数据的 C++ fstream << 和 >> 运算符

c++ - 临时数组的元素本身不是右值吗?

c++ - 三元运算符为什么以及何时返回左值?

c++ - C++ 中转换函数模板参数推导的含义