After this lesson, you will be able to: Use rvalue references, move constructors, std::move, and understand when the compiler elides copies.
Move semantics is the C++11 feature that made modern C++ fast. It's why std::vector<std::string> doesn't copy strings when you reallocate.
Old C++: returning a vector by value copied every element. New C++: moves the internal pointer + size + capacity from old to new object. O(1) instead of O(n). Same for std::string, std::unique_ptr, anything that owns a heap resource.
Two reference types: `T&` for lvalues (named things), `T&&` for rvalues (temporaries).
#include <string>#include <utility>void take(std::string s) { /* by value */ }void takeLRef(std::string& s) { /* lvalue ref */ }void takeRRef(std::string&& s) { /* rvalue ref */ }std::string a = "hello";take(a); // copies a into stake(std::string("x")); // temporary, could move-construct s (compiler chooses)// std::move CASTS to rvalue ref. Doesn't actually move; it tells the next// operation 'you're allowed to steal from this'.take(std::move(a)); // moves a into s. a is now in 'moved-from' state.// a is still a valid object but its contents are unspecified, don't use without reassigning.
Define them when you wrap a resource. Otherwise let the compiler synthesize.
class Buffer {int* data_;size_t size_;public:Buffer(size_t n) : data_(new int[n]), size_(n) {}~Buffer() { delete[] data_; }// Move constructor, steal the pointer; null out sourceBuffer(Buffer&& other) noexcept: data_(other.data_), size_(other.size_) {other.data_ = nullptr;other.size_ = 0;}// Move assignmentBuffer& operator=(Buffer&& other) noexcept {if (this != &other) {delete[] data_;data_ = other.data_;size_ = other.size_;other.data_ = nullptr;other.size_ = 0;}return *this;}// Disable copy for non-copyable resourceBuffer(const Buffer&) = delete;Buffer& operator=(const Buffer&) = delete;};
Copy elision: compiler skips copy/move entirely in certain return-value contexts. RVO (Return Value Optimization): `return Buffer(100);` constructs directly in caller's storage. NRVO (Named RVO): `Buffer b; ...; return b;` similarly. C++17 mandates copy elision in many contexts. Result: you write returning-by-value code; compiler makes it fast.
Using a moved-from object (UB-adjacent; technically valid but unspecified state). Forgetting `noexcept` on move operations (silent perf loss). `std::move`-ing a return value (defeats RVO). Just `return x;`. Move-ing const objects (becomes a copy silently).
Sign in and purchase access to unlock this lesson.