--- 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. ![](https://i.imgur.com/CPrIdMg.png) 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