The traditional C++ reference, now called an lvalue reference, binds an identifier to an lvalue.An lvalue is an expression, such as a variable name or a dereferenced pointer, that represents data for which the program can obtain an address. Originally, an lvalue was one that could appear on the left side of an assignment statement, but the advent of the const modifier allowed for constructs that cannot be assigned to but which are still addressable:
int * pt = new int;
const int b = 101; // can't assign to b, but &b is valid
int & rn = n; // n identifies datum at address &n
int & rt = *pt; // *pt identifies datum at address pt
const int & rb = b; // b identifies const datum at address &b
C++11 adds the rvalue reference , indicated by using
&&, that can bind to rvalues—that is, values that can appear on the right-hand side of an assignment expression but for which one cannot apply the address operator. Examples include literal constants (aside from C-style strings, which evaluate as addresses), expressions such as x+y, and function return values, providing the function does not return a reference:
int x = 10;
int y = 23;
int && r1 = 13;
int && r2 = x + y;
double && r3 = std::sqrt(2.0);
Note that what r2 really binds to is the value to which x + y evaluates at that time. That is, r2 binds to the value 23, and r2 is unaffected by subsequent changes to x or y.
Interestingly, binding an rvalue to an rvalue reference results in the value being stored in a location whose address can be taken.That is, although you can’t apply the & operator to 13, you can apply it to r1.This binding of the data to particular addresses is what makes it possible to access the data through the rvalue references.
One of the main reasons for introducing the rvalue reference is to implement move semantics, the next topic in this chapter.