L 和 R 参考变量

L and R reference variable

我试图理解 Rvalue 和 Lvalue 引用变量的基本概念,以及它们如何相互转换(如果可能)作为变量的函数参数,并理解它们所涉及的内存操作 -因此,我使用所需的 CTors 和 Dtor 创建了一个 class 以了解操作期间的临时对象创建/销毁:

class A
{
public:
   A() {std::cout << "CTor Called" << std::endl;}
   A(const A& a) {std::cout << "Copy CTor Called" << std::endl;}
   A(A&& a) {std::cout << "MOve CTor Called" << std::endl; }
   void operator =(const A& a){std::cout << "operator= Called" << std::endl;}
   ~A() {std::cout << "DTor Called" << std::endl;}
   void Show(){std::cout << "Show Called" << std::endl;}
};

首先我能够创建 R & L 值参考变量:

    A a;
    A& a1 = a;
    const A& a2 = A(); // Lvalue using Rvalue
   //But I am unable to create R refererence variable using an L value variable
    A&& ra = a; // Does not work
    A&& ra = A(); // works

R值引用变量是否只能由R值创建,不像L值可以使用R值创建

现在我编写了以下模板:

template <class T> void fooNoRef(T tmp){tmp.Show();}
template <class T> void fooLRef(T& tmp){tmp.Show();}
template <class T> void fooRRef(T&& tmp){tmp.Show();}

但是我无法使用 R 值引用变量调用 fooRRef 函数模板:

int main()
{
    A a;
    A& a1 = a;
    const A& a2 = A();
    A&& ra = A();
    std::cout << "Calling fooNoRef Template Function" << std::endl;
    fooNoRef<A>(a);
    std::cout << "Calling fooLRef Template Function" << std::endl;
    fooLRef<A>(a);
    std::cout << "Calling fooRRef Template Function With Lvalue" << std::endl;
    fooRRef<A>(ra); // Does not works??
    fooRRef<A>(A());
}

那么R和L参考变量是什么概念,如何使用呢?

But I am unable to call fooRRef function template using R value reference variable:

您混淆了 类型 value categories。作为命名变量,ra 是一个左值,因此不能绑定到右值引用。

(强调我的)

Each C++ expression (an operator with its operands, a literal, a variable name, etc.) is characterized by two independent properties: a type and a value category.

The following expressions are lvalue expressions:

  • the name of a variable, a function, a template parameter object (since C++20), or a data member, regardless of type, such as std::cin or std::endl. Even if the variable's type is rvalue reference, the expression consisting of its name is an lvalue expression;

另一方面,它可以绑定到左值引用,例如

fooLRef<A>(ra); // works

您也可以通过std::move将其显式转换为右值,例如

fooRRef<A>(std::move(ra)); // works

Names of rvalue reference variables are lvalues and have to be converted to xvalues to be bound to the function overloads that accept rvalue reference parameters, which is why move constructors and move assignment operators typically use std::move: