📜  通过示例了解 CC++ 中的 Lvalues、PRvalues 和 Xvalues(1)

📅  最后修改于: 2023-12-03 14:58:07.371000             🧑  作者: Mango

通过示例了解 C++ 中的 Lvalues、PRvalues 和 Xvalues

在 C++ 中,每个表达式都可以分为一种“值类别”(value category):lvalue、prvalue 和 xvalue。了解这些值类别对于理解 C++ 的语言特性和实现机制非常重要。

Lvalues

lvalue 表示“左值”。在 C++ 的最初版本中,所有的变量都是左值,即可以出现在赋值语句的左边。例如:

int a = 1; // 'a' 是一个左值
a = 2;     // 'a' 是一个左值

但随着 C++ 发展,一些语言特性(比如 C++11 中的移动语义)需要引入新的值类别。这使得 lvalue 的定义发生了变化:现在,lvalue 表示“可以取地址的表达式”。也就是说,它必须代表某个具体的对象或函数,而不是常量或计算结果。例如:

int a = 1; // 'a' 是一个 lvalue
int b = a; // 'a' 是一个 lvalue,'b' 是一个 prvalue
PRvalues

prvalue 表示“纯右值”(pure rvalue)。它是在表达式求值之后产生的不可变的值。比如:

int a = 1;   // 'a' 是一个 lvalue
int b = a+2; // 'a+2' 是一个 prvalue,'b' 是一个 lvalue

在 C++ 11 中,prvalue 值类别被分为两种:纯右值 (PRvalue) 和 xvalue。

Xvalues

xvalue 表示“可扩展右值引用”。它是 C++11 中新增的值类别之一。xvalue 既可以被认为是右值,也可以被认为是左值。它表示“可以被移动的、即将销毁的值”。比如:

class A {
public:
  A(A&& rhs) { /* 移动构造函数 */ };
  A& operator=(A&& rhs) { /* 移动赋值函数 */ };
};

A foo(); // 返回一个 A 对象的右值

int main() {
  A a = foo();      // 'foo()' 是一个 prvalue,'a' 是一个 xvalue
  A&& b = foo();    // 'foo()' 是一个 prvalue,'b' 是一个 xvalue 引用
  return 0;
}

在 C++11 中,我们可以通过 std::move 将一个左值转化为 xvalue:

int a = 1;
int&& b = std::move(a); // 'a' 是一个左值,'b' 是一个 xvalue 引用
总结
  • lvalue:可取地址的表达式,代表某个具体的对象或函数
  • prvalue:不可变的值,在求值后产生
  • xvalue:可扩展右值引用,代表即将销毁的值