在线文档教程
C++
语言 | Language

Value categories

Value categories

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. Each expression has some non-reference type, and each expression belongs to exactly one of the three primary value categories: prvalue, xvalue, lvalue, defined as follows:

  • a glvalue is an expression whose evaluation determines the identity of an object, bit-field, or function

Note: this taxonomy went through significant changes with past C++ standard revisions, see History below for details.

Primary categories

lvalue

The following expressions are lvalue expressions:

  • the name of a variable or a function in scope, 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;

a function call or an overloaded operator expression of rvalue reference to function return type; a cast expression to rvalue reference to function type, such as static_cast(x).(since C++11)

  • a function call or an overloaded operator expression of rvalue reference to function return type;

(since C++11)

Properties:

  • Same as glvalue (below).

prvalue

The following expressions are prvalue expressions:

  • a literal (except for string literal), such as 42, true or nullptr;

a lambda expression, such as { return x * x; }.(since C++11)

  • a lambda expression, such as [](int x){ return x * x; }.

(since C++11)

Properties:

  • Same as rvalue (below).

xvalue

The following expressions are xvalue expressions:

  • a function call or an overloaded operator expression of rvalue reference to object return type, such as std::move(x

any expession that designates a temporary object, after temporary materialization(since C++17)

  • any expession that designates a temporary object, after temporary materialization

(since C++17)

Properties:

  • Same as rvalue (below).

In particular, like all rvalues, xvalues bind to rvalue references, and like all glvalues, xvalues may be polymorphic, and non-class xvalues may be cv-qualified.

Mixed categories

glvalue

A glvalue expression is either lvalue or xvalue.

Properties:

  • A glvalue may be implicitly converted to a prvalue with lvalue-to-rvalue, array-to-pointer, or function-to-pointer implicit conversion.

rvalue

An rvalue expression is either prvalue or xvalue.

Properties:

  • Address of an rvalue may not be taken: &int(), &i++[3], &42, and &std::move(x) are invalid.

An rvalue may be used to initialize an rvalue reference, in which case the lifetime of the object identified by the rvalue is extended until the scope of the reference ends. When used as a function argument and when two overloads of the function are available, one taking rvalue reference parameter and the other taking lvalue reference to const parameter, an rvalue binds to the rvalue reference overload (thus, if both copy and move constructors are available, an rvalue argument invokes the move constructor, and likewise with copy and move assignment operators).(since C++11)

  • An rvalue may be used to initialize an rvalue reference, in which case the lifetime of the object identified by the rvalue is extended until the scope of the reference ends.

(since C++11)

Special categories

Pending member function call

The expressions a.mf and p->mf, where mf is a non-static member function, and the expressions a.*mfp and p->*mfp, where mfp is a pointer to member function, are classified as prvalue expressions, but they cannot be used to initialize references, as function arguments, or for any purpose at all, except as the left-hand argument of the function call operator, e.g. (p->*mfp)(args).

Void expressions

Function call expressions returning void, cast expressions to void, and throw-expressions are classified as prvalue expressions, but they cannot be used to initialize references or as function arguments. They can be used in discarded-value contexts (e.g. on a line of its own, as the left-hand operand of the comma operator, etc.) and in the return statement in a function returning void. In addition, throw-expressions may be used as the second and the third operands of the conditional operator ?:.

Void expressions have no result object.(since C++17)

Bit fields

An expression that designates a bit field (e.g. a.m, where a is an lvalue of type struct A { int m: 3; }) is an lvalue expression: it may be used as the left-hand operand of the assignment operator, but its address cannot be taken and a non-const lvalue reference cannot be bound to it. A const lvalue reference can be initialized from a bit-field lvalue, but a temporary copy of the bit-field will be made: it won't bind to the bit field directly.

History

CPL

The programming language CPL(http://en.wikipedia.com/wiki/CPL_(programming_language%29) was first to introduce value categories for expressions: all CPL expressions can be evaluated in "right-hand mode", but only certain kinds of expression are meaningful in "left-hand mode". When evaluated in right-hand mode, an expression is regarded as being a rule for the computation of a value (the right-hand value, or rvalue). When evaluated in left-hand mode an expression effectively gives an address (the left-hand value, or lvalue). "Left" and "Right" here stood for "left of assignment" and "right of assignment".

C

The C programming language followed a similar taxonomy, except that the role of assignment was no longer significant: C expressions are categorized between "lvalue expressions" and others (functions and non-object values), where "lvalue" means an expression that identifies an object, a "locator value"[4]

C++98

Pre-2011 C++ followed the C model, but restored the name "rvalue" to non-lvalue expressions, made functions into lvalues, and added the rule that references can bind to lvalues, but only references to const can bind to rvalues. Several non-lvalue C expressions became lvalue expressions in C++.

C++11

With the introduction of move semantics in C++11, value categories were redefined to characterize two independent properties of expressions[5]:

  • has identity: it's possible to determine whether the expression refers to the same entity as another expression, such as by comparing addresses of the objects or the functions they identify (obtained directly or indirectly

In C++11, expressions that:

  • have identity and cannot be moved from are called lvalue expressions;

The expressions that have identity are called "glvalue expressions" (glvalue stands for "generalized lvalue"). Both lvalues and xvalues are glvalue expressions.

The expressions that can be moved from are called "rvalue expressions". Both prvalues and xvalues are rvalue expressions.

C++17

In C++17, copy elision was made mandatory in some situations, and that required separation of prvalue expressions from the temporary objects initialized by them, resulting in the system we have today.

Footnotes

  • Assuming i has built-in type or the pre-increment operator is overloaded to return by lvalue reference

Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DRApplied toBehavior as publishedCorrect behavior
CWG 616C++11member access and member access through pointer to member of an rvalue resulted in prvaluereclassified as xvalue
CWG 1213C++11subscripting an array rvalue resulted in lvaluereclassified as xvalue

See also

| C documentation for value categories |

|:----|

© cppreference.com

Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.

http://en.cppreference.com/w/cpp/language/value_category