| title | Value Categories: Lvalues and Rvalues (Visual C++) | Microsoft Docs | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ms.custom | ||||||||||||||
| ms.date | 11/04/2016 | |||||||||||||
| ms.reviewer | ||||||||||||||
| ms.suite | ||||||||||||||
| ms.technology |
|
|||||||||||||
| ms.tgt_pltfrm | ||||||||||||||
| ms.topic | language-reference | |||||||||||||
| dev_langs |
|
|||||||||||||
| helpviewer_keywords |
|
|||||||||||||
| ms.assetid | a8843344-cccc-40be-b701-b71f7b5cdcaf | |||||||||||||
| caps.latest.revision | 14 | |||||||||||||
| author | mikeblome | |||||||||||||
| ms.author | mblome | |||||||||||||
| manager | ghogen | |||||||||||||
| translation.priority.ht |
|
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. In C++17 (Visual Studio version 15.3 and later) the rules were restated to ensure that all compilers behave identically by not creating objects unless they are actually required. The new specified behavior is called "guaranteed copy elision." It helps to make your code more portable and efficient and eliminates the need to provide copy and move constructors for types that never use them.
The C++17 standard defines expression value categories as follows:
- A glvalue is an expression whose evaluation determines the identity of an object, bit-field, or function.
- 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.
- 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). [ 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. ]
- An lvalue is a glvalue that is not an xvalue.
- An rvalue is a prvalue or an xvalue.
Examples of lvalue expressions include variable names, including const variables, array elements, bit-fields, unions, and class members. Examples of rvalue expressions include literals, function calls, and temporary objects that are created during expression evalution but accessible only by the compiler.
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;
const int ci = 7;
// Incorrect usage: the variable is a non-modifiable lvalue (C3892).
ci = 9; // C3892
// Correct usage: the conditional operator returns an lvalue.
((i < 3) ? i : j) = 7;
}
Note
The examples in this topic illustrate correct and incorrect usage when operators are not overloaded. By overloading operators, you can make an expression such as j * 4 an lvalue.
The following example shows the new behavior for guaranteed copy elision. Note that construction from temporary objects succeeds in both cases despite the absence of a move constructor.
#include <iostream>
#include <string>
using namespace std;
struct S {
S(int) { cout << "S(int)" << endl; }
S(S&) = delete;
S(S&&) = delete; // { cout << "move" << endl; }
///...
};
S make_s()
{
// Return value initialized directly at call site.
// In Visual Studio 2015 this does not compile due to deleted move ctor.
return S(42);
}
int main()
{
auto nm = make_s();
S x4 = 5; // Construct from an rvalue.
}The program produces this output:
S(int)
S(int)
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: &&.
Basic Concepts
Lvalue Reference Declarator: &
Rvalue Reference Declarator: &&