Before understanding about this new feature “Rvalue references” of C++11(Introduction to C++11), we should first understand what is lvalue and rvalue in C++.
Typically Lvalue is an expression which returns a permanent memory address which can be assigned to any variables. For ex:
int x = 10; int y; y = 20;
Here both x and y are lvalues. In some cases, we can have functions also as lvalue as shown in below example:
int x; // global variable // Returning reference to global variable x int& getXRef() { return x; } getXRef() = 30;
Now this function can act as lvalue too as shown above.
Typically Rvalue is an expression which returns a temporary memory address and thus we can’t use this to assign/modify any value to this. For ex:
int i = 1; int j = 2; int k = i * j; // here "i * j" is a Rvalue which can be used on RHS side of assignment. i * j = k; // Since "i * j" is a Rvalue, hence we can't use it on LHS side of assignment. This will lead into compile time error.
Typically functions which are not returning references are rvalues. For ex:
int x = 20; // global variable int getX() { return x; } int y = getX(); // here "getX()" is an rvalue which can be used on RHS side of assignement. getX() = 70; // Error as rvalue can't be used on LHS side of the assignment.
Rvalue References
Rvalue reference will allow to bind a mutable reference to an rvalue only and its not allowed to use it for lvalue. Rvalue refernece syntax uses “&&” instead of “&” which is used for reference to lvalue.
Let’s take an example below to clarify the doubts:
#include <iostream> using namespace std; int yy = 10; int getYY() { return yy; } void printX(const int& x) { cout<<"Value of x: "<<x<<endl; } void printX(int&& x) { cout<<"Rvalue Value of x: "<<x<<endl; } void main() { int a = 20; int b = getYY(); printX(b); // This is an example of lvalue reference and hence first printX function is called printX(a); // This is an example of lvalue reference and hence first printX function is called printX(getYY()); // This is an example of rvalue reference and hence second printX function is called }
Output of above program is as follows:
Value of x: 10 Value of x: 20 Rvalue Value of x: 10
Some important points related to rvalue references:
- In case of second overloaded function “printX(int&& x)” is not implemented then first version of “printX(const int& x)” will be called for both cases.
- In case of first overloaded function “printX(const int& x)” is not implemented then “printX(a)” will result in Compile time error as “printX(int&& x)” can be only called for rvalues and not for lvalues.
- Typically any function can be overloaded in the manner shown above but usually these kind of overloading is used for copy constructors and assignment constructor to implement “move constructors” which will give better performance compare to traditional constructors which we will see in next section related to “move constructors”