Lesson 20 • Advanced
Move Semantics, Perfect Forwarding & Rvalue References
Deep dive into rvalue references, std::forward, perfect forwarding, and copy elision — the mechanics that make modern C++ fast.
What You'll Learn
- ✓ Lvalue vs rvalue references (& vs &&)
- ✓ Perfect forwarding with std::forward
- ✓ Forwarding references vs rvalue references
- ✓ RVO, NRVO, and guaranteed copy elision
Lvalue vs Rvalue — Value Categories
Every expression in C++ has a value category. An lvalue has an identity — you can take its address. An rvalue is a temporary that's about to be destroyed. Rvalue references (&&) let you "catch" temporaries and steal their resources instead of copying.
| Category | Examples | Can take address? |
|---|---|---|
| lvalue | x, arr[0], *ptr, obj.member | Yes (&x) |
| rvalue | 42, x+y, "hello", func() | No |
| xvalue | move(x), static_cast<T&>(x) | Expiring lvalue |
Rvalue References
Understand lvalue vs rvalue references and overload resolution
#include <iostream>
#include <string>
using namespace std;
// lvalue reference: binds to named objects
void processLvalue(string& s) {
cout << "lvalue ref: " << s << endl;
}
// rvalue reference: binds to temporaries
void processRvalue(string&& s) {
cout << "rvalue ref: " << s << endl;
// s itself is an lvalue inside this function!
// Even though it was bound to an rvalue
}
// Overload resolution picks the right version
void process(const string& s) {
cout << "const lvalue
...Perfect Forwarding with std::forward
Perfect forwarding passes arguments to another function preserving their original value category. If the caller passed an rvalue, the inner function receives an rvalue. If an lvalue, it stays an lvalue. This is essential for factory functions, emplace methods, and generic wrappers.
The trick: use a forwarding reference (T&& where T is deduced) combined with std::forward<T>(arg).
Perfect Forwarding
Forward arguments preserving their lvalue/rvalue category
#include <iostream>
#include <string>
#include <memory>
#include <utility>
using namespace std;
class Widget {
string name;
int value;
public:
Widget(const string& n, int v) : name(n), value(v) {
cout << "Widget(copy '" << name << "')" << endl;
}
Widget(string&& n, int v) : name(move(n)), value(v) {
cout << "Widget(move '" << name << "')" << endl;
}
void show() const { cout << name << " = " << value << endl; }
};
// Perfect forwarding: preserves valu
...Copy Elision & RVO
See how the compiler eliminates unnecessary copies and moves
#include <iostream>
#include <vector>
using namespace std;
class Heavy {
vector<int> data;
string label;
public:
Heavy(string l, int n) : label(l), data(n, 42) {
cout << "[" << label << "] Constructed (" << n << " ints)" << endl;
}
Heavy(const Heavy& o) : data(o.data), label(o.label + "_copy") {
cout << "[" << label << "] COPIED" << endl;
}
Heavy(Heavy&& o) noexcept : data(move(o.data)), label(move(o.label) + "_moved") {
cout << "[" << label <
...Common Mistakes
⚠️ Forwarding ref vs rvalue ref: T&& is a forwarding ref only when T is deduced. string&& is always an rvalue ref.
⚠️ Using std::move in return: Don't return move(local); — it prevents copy elision. Just return local;.
⚠️ Forwarding more than once: forward may move the argument. Forwarding the same argument twice can use a moved-from object.
Pro Tips
💡 Rule of thumb: Use std::move on rvalue references, std::forward on forwarding references. Never mix them.
💡 Rely on copy elision: In C++17, returning a prvalue is guaranteed to elide. Write clean code and let the compiler optimise.
💡 noexcept matters: Mark move operations noexcept so containers use move instead of copy during reallocation.
📋 Quick Reference
| Concept | Syntax |
|---|---|
| Rvalue reference | T&& r = move(x); |
| Forwarding ref | template<typename T> void f(T&& x) |
| Perfect forward | forward<T>(x) |
| Cast to rvalue | move(x) |
| Guarantee elision | return T(args); (C++17) |
Lesson Complete!
You now understand the deep mechanics of move semantics, perfect forwarding, and copy elision. Next: RAII Architecture — applying resource ownership patterns across complex systems.
Sign up for free to track which lessons you've completed and get learning reminders.