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 of 5.

Another example

string f() {
	return "Hello World";
}
string S = f();
  • this expression f() is an rvalue. The returned result of f 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 as s 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 address s 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.