Lvalues 和 Rvalues (C++)Lvalues and Rvalues (C++)

每个 C++ 表达式有一个类型,并且属于值类别Every C++ expression has a type, and belongs to a value category. 值类别是在创建、 复制和移动在表达式计算期间的临时对象时,编译器必须遵循的规则的基础。The value categories are the basis for rules that compilers must follow when creating, copying, and moving temporary objects during expression evaluation.

C++ 17 标准定义表达式值的分类,如下所示:The C++17 standard defines expression value categories as follows:

  • 一个glvalue是的表达式的求值结果确定标识的对象、 位域或函数。A glvalue is an expression whose evaluation determines the identity of an object, bit-field, or function.
  • 一个prvalue是的表达式的求值结果初始化对象或一个位字段,或在它所出现的上下文中的指定计算运算符的操作数的值。A prvalue is an expression whose evaluation initializes an object or a bit-field, or computes the value of the operand of an operator, as specified by the context in which it appears.
  • Xvalue是 glvalue 表示的对象或位域可以重复使用的资源,(通常是因为它即将达到其生命周期结束)。An xvalue is a glvalue that denotes an object or bit-field whose resources can be reused (usually because it is near the end of its lifetime). 示例:特定类型的表达式涉及右值引用 (8.3.2) 产生 xvalues,如对其返回类型是右值引用的函数的调用或强制转换为右值引用类型。Example: Certain kinds of expressions involving rvalue references (8.3.2) yield xvalues, such as a call to a function whose return type is an rvalue reference or a cast to an rvalue reference type.
  • 左值是不是 xvalue glvalue。An lvalue is a glvalue that is not an xvalue.
  • 右值prvalue 或 xvalue。An rvalue is a prvalue or an xvalue.

下图演示了两个分类之间的关系:The following diagram illustrates the relationships between the categories:

C++ 表达式值的分类C++ expression value categories

左值具有您的程序可以访问的地址。An lvalue has an address that your program can access. 左值表达式的示例包括变量的名称,包括const变量,数组元素、 函数返回的左值引用、 位域、 联合和类成员的调用。Examples of lvalue expressions include variable names, including const variables, array elements, function calls that return an lvalue reference, bit-fields, unions, and class members.

Prvalue 表达式具有可访问你的程序没有地址。A prvalue expression has no address that is accessible by your program. Prvalue 表达式的示例包括文本、 非引用类型返回的函数调用和仅由编译器创建表达式评估期间,但可访问的临时对象。Examples of prvalue expressions include literals, function calls that return a non-reference type, and temporary objects that are created during expression evalution but accessible only by the compiler.

Xvalue 表达式具有一个地址,无法再访问你的程序,但可用于初始化右值引用,它提供与表达式的访问。An xvalue expression has an address that no longer accessible by your program but can be used to initialize an rvalue reference, which provides access to the expression. 示例包括返回右值引用的数组下标、 成员和指针到成员表达式,数组或对象是右值引用的函数调用。Examples include function calls that return an rvalue reference, and the array subscript, member and pointer to member expressions where the array or object is an rvalue reference.

示例Example

以下示例演示左值和右值的多种正确的和错误的用法:The following example demonstrates several correct and incorrect usages of lvalues and rvalues:

// 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
}

备注

此主题中的示例阐释了未重载运算符时的正确和错误用法。The examples in this topic illustrate correct and incorrect usage when operators are not overloaded. 通过重载运算符,可以使表达式(如 j * 4)成为左值。By overloading operators, you can make an expression such as j * 4 an lvalue.

条款左值右值通常用于在引用对象的引用时。The terms lvalue and rvalue are often used when you refer to object references. 有关引用的详细信息,请参阅左值引用声明符: &右值引用声明符: & &For more information about references, see Lvalue Reference Declarator: & and Rvalue Reference Declarator: &&.

请参阅See also

基本概念Basic Concepts
Lvalue 引用声明符:&Lvalue Reference Declarator: &
规则引用声明符:&&Rvalue Reference Declarator: &&