Value Category (lvalue and rvalue)
Learned in CS247. This is used for the Move Assignment Operator.
Every expression in C++ has both a type and a Value Category.
lvalue
An lvalue is any expression that you can take the address of.
For example:
int x = 5;
f(x);
- In the above, this expression
x
- we can take its address, therefore it is an lvalue.
rvalue
An rvalue is a temporary value, it will be destroyed “soon”.
f(5)
5
is an rvalue, as we cannot take the address of5
.
Another example
string f() {
return "Hello World";
}
string S = f();
- this expression
f()
is an rvalue. The returned result off
only exists until the end of the line
We cannot run &f()
- the string isn’t stored anywhere permanently, just a temporary until it is saved into s
The references we have seen so far are lvalue references. These can only bind to expressions that are lvalues.
For example:
int x = 5;
int& y = x; // âś“ this is good
However,
int& y = 5; // âś• this doesn't compile. 5 is an rvalue.
An exception: We can bind rvalues to const lvalue references.
f(int& x) {
...
}
f(5) // âś• prohibited
g(const int& x) {
...
}
g(5); // âś“ this is allowed, we won't modify x, the compiler creates a temporary memory location to store the 5 in.
rvalue reference
We can create rvalue references. This extends the lifetime of the rvalue to the lifetime of the reference.
String f() {
return "Hello World";
}
String&& s = f(); // String&& is an rvalue reference
- We can use the temporary value returned by
f
for as long ass
exists.
Most commonly used for overloading functions based on the value category of the expression.
void f(const string& s) {
cout << "1" << endl;
}
void f(string&& s) {
cout << "2" << endl;
}
string s{"cs247"};
f(s); // "1"
f(string{"CS247"}); // "2"
Why is this useful? We’ll see shortly.
Finally, note that type and value categories are independent properties.
void f(string&& s) {
cout << s << endl;
}
- Here, although
s
references an rvalue, we can take s’s addresss
is an lvalue.
xvalue? https://en.cppreference.com/w/cpp/language/value_category
- a glvalue (“generalized” lvalue) is an expression whose evaluation determines the identity of an object or function;
- a prvalue (“pure” rvalue) is an expression whose evaluation
- computes the value of an operand of a built-in operator (such prvalue has no result object), or
- initializes an object (such prvalue is said to have a result object).
- The result object may be a variable, an object created by new-expression, a temporary created by temporary materialization, or a member thereof. Note that non-void discarded expressions have a result object (the materialized temporary). Also, every class and array prvalue has a result object except when it is the operand of decltype;
- an xvalue (an “eXpiring” value) is a glvalue that denotes an object whose resources can be reused;
- an lvalue (so-called, historically, because lvalues could appear on the left-hand side of an assignment expression) is a glvalue that is not an xvalue;
- an rvalue (so-called, historically, because rvalues could appear on the right-hand side of an assignment expression) is a prvalue or an xvalue.