What are Move Semantics in C++?
Master C++ move semantics: rvalue references, move constructors, std::move, the Rule of Five, and how moving resources avoids costly deep copies for speed.
Expected Interview Answer
Move semantics let a C++ object transfer ownership of its resources (like heap memory) to another object instead of copying them, using rvalue references (T&&), a move constructor, and a move assignment operator.
Introduced in C++11, move semantics avoid expensive deep copies of temporaries and objects being discarded. When you move from an object, the target steals the source's internal pointers/handles and leaves the source in a valid but unspecified (typically empty) state. std::move is a cast to an rvalue reference that enables this. The compiler picks move operations for rvalues (temporaries) automatically, and the Rule of Five means declaring one special member usually means defining the destructor, copy, and move operations. Perfect forwarding via std::forward preserves value categories in templates.
- Eliminates costly deep copies of temporaries
- Transfers ownership of heap resources cheaply
- Improves performance of containers like std::vector
- Enables move-only types such as std::unique_ptr
- Supports perfect forwarding in generic code
AI Mentor Explanation
Instead of building a brand-new identical stadium for an away game, the touring team simply takes over the existing ground and its facilities for the match, leaving the old venue empty. Move semantics do this with resources: the new object seizes the source's internal buffers rather than copying them, leaving the source hollow but valid.
Step-by-Step Explanation
Step 1
Recognize rvalues
Temporaries and expiring objects bind to rvalue references (T&&), which move operations target.
Step 2
Define the move constructor
Steal the source's pointers/handles, then null them out so the source stays valid and safe to destroy.
Step 3
Define move assignment
Release current resources, take the source's, and reset the source, guarding against self-assignment.
Step 4
Use std::move
Cast an lvalue to an rvalue reference when you knowingly no longer need it, enabling a move.
Step 5
Honor the Rule of Five
If you define any of destructor, copy or move members, consider defining all five for correctness.
What Interviewer Expects
- Difference between copy and move semantics
- Understanding of rvalue references and value categories
- Correct move constructor / move assignment implementation
- Knowing std::move is just a cast, not a move itself
- Awareness of the Rule of Five and move-only types
Common Mistakes
- Thinking std::move actually moves something (it only casts)
- Forgetting to leave the moved-from object in a valid state
- Adding const to return types, preventing moves
- Writing throwing move constructors instead of noexcept ones
- Using a moved-from object as if it still holds its resource
Best Answer (HR Friendly)
“Move semantics let C++ hand over an object's resources to another object instead of making an expensive copy. It's like giving someone your keys rather than building them a duplicate house, which makes programs faster when dealing with large temporary data.”
Code Example
#include <utility>
#include <cstring>
class Buffer {
char* data_;
std::size_t size_;
public:
Buffer(std::size_t n) : data_(new char[n]), size_(n) {}
~Buffer() { delete[] data_; }
// Move constructor: steal the resource
Buffer(Buffer&& other) noexcept
: data_(other.data_), size_(other.size_) {
other.data_ = nullptr; // leave source valid
other.size_ = 0;
}
// Move assignment
Buffer& operator=(Buffer&& other) noexcept {
if (this != &other) {
delete[] data_;
data_ = other.data_;
size_ = other.size_;
other.data_ = nullptr;
other.size_ = 0;
}
return *this;
}
};
int main() {
Buffer a(1024);
Buffer b(std::move(a)); // move, no deep copy
return 0;
}Follow-up Questions
- What does std::move actually do under the hood?
- Why should move constructors be marked noexcept?
- What is the Rule of Five and why does it matter?
- How does perfect forwarding with std::forward work?
- What state should a moved-from object be left in?
MCQ Practice
1. What does std::move actually do?
std::move performs an unconditional cast to an rvalue reference; the actual move happens in the move constructor/assignment that gets selected.
2. After being moved from, an object should be left in what state?
A moved-from object must remain valid (safe to destroy or reassign) though its value is unspecified, typically empty.
3. Why should move constructors be noexcept?
std::vector only uses a move constructor during reallocation if it is noexcept; otherwise it falls back to copying to preserve the strong guarantee.
Flash Cards
What are move semantics? — Transferring ownership of an object's resources to another object instead of copying them, via rvalue references.
What is std::move? — A cast that turns an lvalue into an rvalue reference, enabling a move constructor or move assignment to be selected.
What state is a moved-from object in? — Valid but unspecified — safe to destroy or reassign, typically emptied.
What is the Rule of Five? — If you define any of destructor, copy ctor, copy assign, move ctor, or move assign, you likely need all five.