---
tags: CSE
---
value categories have a long history, but i'll only talk value categories in c\++11 (including c\++14, 17, 20).
in c++11, 5 value categories are introduced.

as shown, there're 3 primary value categories:
1. lvalue
2. xvalue
3. prvalue
and 2 mixed value categories:
1. glvalue = lvalue + xvalue
2. rvalue = prvalue + xvalue
if you fully understand the 3 primary value categories, these 2 kinds aren't worth discussing.
so i won't talk these two.
## lvalue
lvalue is the object which __can be used more than once.__
the address of lvalue can be taken by built-in address-of operator: ```&```.
there're lots of trivial lvalue expression. for example, the name of a variable, including a rvalue reference, a function, or a data member, regardless of type, such as ```std::cin``` or ```std::endl```.
```cpp=
int a; // not an expression but a statement
a; // lvalue expression
void f() {} // not an expression, but a statement
f; // lvalue expression
int&& r; // not an expression, but a statement
r; // lvalue expression
```
a function return a lvalue reference is a lvalue expression.
```cpp=
struct complex
{
double re, im;
complex(double r, double i): re{r}, im{i} {}
complex& operator+=(const complex& rhs)
{
this->im += rhs.im, this->re += rhs.re;
return *this;
}
complex& operator++()
{
++this->re;
return *this;
}
}A{1,0}, B{-1, 1};
A += B; // lvalue expression
A.operator+=(B); // equivalent
++A; // lvalue expression
A.operator++(); // equivalent
std::cout << "emilia " << "best"; // lvalue expression
(std::cout.operator<<("emilia ")).operator("best"); // equivalent
```
and built-in assignment and compound assignment (```x = 1, x += 1```), built-in pre-increment and pre-decrement (```++x, --x```), the built-in indirection expression (```*p```) are lvalue expression.
note that the built-in subscript expressions (```a[n]```) and the member of object expression(```a.m```) are lvalue, __only when the ```a``` is lvalue__ and ```m``` is not a non-static member function.
```cpp=
int a[N];
a[i]; // lvalue expression
((int[N]){0,1,2,3})[i]; // not an lvalue expression
struct A { int x; int f(); }a;
a.x; // lvalue expression
a.f; // not an lvalue expression
A().x; // not an lvalue expression
```
_specially, string literal is lvalue expression._
```cpp=
"Emiliatan Maji Tenshi"; // lvalue
```
_maybe, that's because compiler will put the string literal in data segment._
## prvalue
prvalue is the object which __can be used only once.__
prvalue can't be taken address.
trivial prvalue are literal (except string literal), like ```923```,```true```,```nullptr```, built-in post-increment and post-decrement (```a++,a--```), built-in arithmetic(```a+b,a-b```), built-in logic (```a&&b, a||b```), built-in comparison expression (```a>b, a!=b```), a function call whose return type is non-reference.
the built-in address-of expression, the member of object expression, ```a.m```, where ```m``` is non-static member function.
```cpp=
int v;
&v; // rvalue expression
struct A { int f(); }a;
a.f; // rvalue expression
A().f; // rvalue expression
```
## xvalue
xvalue is the oddest value kind.
the following expression is xvalue:
- a function call return a rvalue reference type
- the built-in subscript expression, ```a[n]```, where ```a``` is an array rvalue
- the member of object expression, ```a.m```, where ```a``` is an rvalue and ```m``` is a non-static data member of non-reference type.
```cpp=
std::string s;
std::move(s); // xvalue expression
using arrN_t int[N];
arrN_t{0,1,2,3}[n]; // xvalue expression
arrN_t arr{0,1,2,3};
std::move(arr)[n]; // xvalue expression
struct A { int m; };
A().m; // xvalue expression
```
an xvalue is just like a prvalue, it can't be taken by built-in address-of operator.
and both xvalue and prvalue can be used to initialize an rvalue reference or a const lvalue reference, in which case the lifetime of the object is extended.
in the same time, xvalue has some lvalue properties:
- may be implicitly converted to a prvalue with lvalue-to-rvalue, array-to-pointer, or function-to-pointer implicit conversion.
- may be polymorphic
- can have incomplete type
that's why glvalue = lvalue + xvalue, rvalue = prvalue + xvalue.
---
## reference
- https://en.cppreference.com/w/cpp/language/value_category
- https://stackoverflow.com/questions/3601602/what-are-rvalues-lvalues-xvalues-glvalues-and-prvalues
- https://hackmd.io/@Mes/Cpp_Miner/https%3A%2F%2Fhackmd.io%2F%40Mes%2FMiner_MoveSemantics#-%E7%A4%A6%E5%9D%91%E7%B3%BB%E5%88%97-%E2%94%80%E2%94%80-%E5%80%BC%E9%A1%9E%E5%88%A5Value-Categoraries