C++ Rvalue References
In this page:
Lvalues vs. Rvalues
An lvalue is an expression that refers to a persistent object with an identifiable memory location, such as a named variable -- you can take its address. An rvalue is a temporary value, like a literal (5) or the return value of a function, which exists only briefly and has no stable address you can rely on.
Example: Lvalues vs. Rvalues
#include <iostream>
int main() {
int x = 5;
int y = x + 1;
std::cout << y << std::endl;
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Rvalue Reference Syntax (&&)
An rvalue reference is declared with a double ampersand (T&&) after the type, and specifically binds to temporaries rather than named variables. This distinct reference type is what lets a function overload detect, at compile time, whether it was handed a temporary that's safe to "steal" resources from.
Example: Rvalue Reference Syntax (&&)
#include <iostream>
void show(int &&x) {
std::cout << "Rvalue reference: " << x << std::endl;
}
int main() {
show(5);
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Binding Constraints
A regular lvalue reference (T&) can only bind to an lvalue -- it can't bind to a temporary at all, since the temporary might be destroyed before the reference could safely be used. Conversely, an rvalue reference (T&&) can't bind to a named variable directly, since that variable is still in active use elsewhere.
Example: Binding Constraints
#include <iostream>
void show(int &x) { std::cout << "lvalue ref" << std::endl; }
void show(int &&x) { std::cout << "rvalue ref" << std::endl; }
int main() {
int a = 5;
show(a);
show(10);
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Casting Lvalues with std::move
std::move() exists specifically to bridge this gap: it casts an lvalue to an rvalue reference, letting you explicitly tell the compiler "I'm done with this variable, treat it as a temporary you're free to move from" even though it has a name and an address.
Example: Casting Lvalues with std::move
#include <iostream>
#include <utility>
void show(int &&x) { std::cout << "rvalue: " << x << std::endl; }
int main() {
int a = 5;
show(std::move(a));
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Overloading with Rvalue References
When both an lvalue-reference and an rvalue-reference overload of a function exist, the compiler automatically picks the rvalue overload for temporaries and function-return values, which is exactly what enables move semantics to kick in transparently without you writing any extra code at the call site.
Example: Overloading with Rvalue References
#include <iostream>
#include <utility>
void process(const int &x) { std::cout << "lvalue overload" << std::endl; }
void process(int &&x) { std::cout << "rvalue overload" << std::endl; }
int main() {
int a = 5;
process(a);
process(10);
process(std::move(a));
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Chapter Quiz — Complete all 9 topics to unlock
0/9 topics done
Complete these topics first: