Lvalues 和 Rvalues (C++)
每个 C++ 表达式都有一个类型,属于值类别。 值类别是编译器在表达式计算期间创建、复制和移动临时对象时必须遵循的规则的基础。
C++17 标准对表达式值类别的定义如下:
- glvalue 是一个表达式,它的计算可以确定对象、位域或函数的标识。
- prvalue 是一个表达式,它的计算可以初始化对象或位域,或计算运算符的操作数值,这是由它出现的上下文所指定的。
- xvalue 是一个 glvalue,表示一个对象或位域,该对象或位域的资源可重复使用(通常是因为它接近其生存期的末尾)。 示例:某些涉及 rvalue 引用 (8.3.2) 的类型的表达式会生成 xvalue,例如对返回类型为 rvalue 引用或强制转换为 rvalue 引用类型的函数的调用。
- lvalue 为非 xvalue 的 glvalue。
- rvalue 是一个 prvalue 或 xvalue。
下图阐释了各类别之间的关系:
该图以带框标记的表达式开头,其有两个子项:glvalue 和 rvalue。 glvalue 有两个子项:lvalue 和 xvalue。 rvalue 有两个子项:prvalue 和 xvalue;xvalue 也是 glvalue 的子项。
lvalue 具有程序可访问的地址。 例如,lvalue 表达式包括变量名称,其中包括 const
变量、数组元素、返回 lvalue 引用的函数调用、位域、联合和类成员。
prvalue 表达式没有可供程序访问的地址。 例如,prvalue 表达式包括文本、可返回非引用类型的函数调用,以及在表达式计算期间创建的但只能由编译器访问的临时对象。
xvalue 表达式有一个地址,该地址不再可供程序访问,但可用于初始化 rvalue 引用,以提供对表达式的访问。 例如,它包括可返回 rvalue 引用的函数调用,以及数组下标、成员和指向其中数组或对象是 rvalue 引用的成员表达式的指针。
示例
以下示例演示左值和右值的多种正确的和错误的用法:
// lvalues_and_rvalues2.cpp
int main()
{
int i, j, *p;
// Correct usage: the variable i is an lvalue and the literal 7 is a prvalue.
i = 7;
// Incorrect usage: The left operand must be an lvalue (C2106).`j * 4` is a prvalue.
7 = i; // C2106
j * 4 = 7; // C2106
// Correct usage: the dereferenced pointer is an lvalue.
*p = i;
// Correct usage: the conditional operator returns an lvalue.
((i < 3) ? i : j) = 7;
// Incorrect usage: the constant ci is a non-modifiable lvalue (C3892).
const int ci = 7;
ci = 9; // C3892
}
注意
此主题中的示例阐释了未重载运算符时的正确和错误用法。 通过重载运算符,可以使表达式(如 j * 4
)成为左值。
在提到对象引用时,通常会使用术语 lvalue 和 rvalue。 有关引用的详细信息,请参阅 lvalue 引用声明符:& 和 Rvalue 引用声明符:&&。
另请参阅
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈