我试图理解Rvalue和Lvalue参考变量的基本概念,以及如何将它们作为变量的函数参数相互转换(如果可能),并理解它们所涉及的内存操作-因此,我总结了具有必需的CTor和Dtor的类,以了解操作期间的临时对象创建/破坏:
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参考变量的概念是什么以及如何使用它们?
但是我无法使用R值参考变量来调用
fooRRef
功能模板:
您对types和value categories感到困惑。作为一个命名变量,ra
是一个左值,因此不能绑定到右值引用。
(重点是我的)
每个C ++表达式(带有其操作数,文字,变量名称等)的特征是两个独立属性:类型和值类别。
以下表达式是左值表达式:
- 变量的名称,函数
, a template parameter object (since C++20)
或数据成员,无论类型如何,例如std::cin
或std::endl
。 即使变量的类型是右值引用,由名称组成的表达式是左值表达式;
另一方面,它可以绑定到左值引用,例如
fooLRef<A>(ra); // works
您还可以通过std::move
将其明确转换为右值,例如
std::move
右值引用变量的名称为左值,必须为转换为xvalues以绑定到接受的函数重载右值参考参数,这就是为什么移动构造函数和移动赋值运算符通常使用
fooRRef<A>(std::move(ra)); // works
: