What is the Rule of Five in C++?
Learn the C++ Rule of Five — move constructor and move assignment alongside the Rule of Three — with examples and interview Q&A.
Expected Interview Answer
The Rule of Five extends the Rule of Three for modern C++ by stating that a resource-owning class should typically define all five special member functions together: destructor, copy constructor, copy assignment operator, move constructor, and move assignment operator.
C++11 introduced move semantics, which let a resource be transferred from a temporary or expiring object to a new one without an expensive deep copy, by stealing the internal pointer and leaving the source in a valid-but-empty state. If a class defines a custom destructor and copy operations but omits move operations, the compiler either implicitly deletes them or falls back to the copy operations, silently losing the performance benefit and sometimes producing surprising behavior. The move constructor takes an rvalue reference (Type&&), transfers ownership of the resource pointer, and nulls out the source’s pointer so its destructor does not free the just-transferred resource. The move assignment operator does the same but must first release any resource the target already owned. Defining all five together keeps a resource-owning class’s copy and move semantics consistent and correct.
- Enables efficient resource transfer instead of expensive deep copies
- Keeps copy and move semantics consistent across the class
- Avoids implicit deletion of move operations that silently degrades performance
- Supports safe use in containers that rely on move semantics, like vector reallocation
AI Mentor Explanation
A ground crew that owns custom mobile floodlight rigs can either duplicate a rig from scratch for a new venue, which is a copy, or physically relocate the exact same rig to the new venue when the old venue no longer needs it, which is a move, leaving the original venue with no rig at all. A move is far cheaper than fabricating a duplicate because you are transferring the existing asset, not rebuilding it. The Rule of Five is exactly this: alongside deep-copy operations, define transfer operations that steal the resource and leave the source empty rather than always paying for a full duplicate.
Step-by-Step Explanation
Step 1
Start from the Rule of Three
Have a correct destructor, copy constructor, and copy assignment operator for the owned resource.
Step 2
Add a move constructor
Accept an rvalue reference, steal the source’s resource pointer, and null out the source pointer.
Step 3
Add a move assignment operator
Release the target’s current resource, steal the source’s pointer, null the source, guard against self-move.
Step 4
Mark move operations noexcept where possible
Lets standard containers like vector prefer moving over copying during reallocation.
What Interviewer Expects
- Clear distinction between copy semantics (duplicate) and move semantics (transfer)
- Explanation of why omitting move operations silently loses a performance benefit
- Mention that move operations should leave the source in a valid, destructible state
- Awareness of noexcept’s role in enabling container optimizations
Common Mistakes
- Forgetting to null out the source pointer in a move constructor, causing a double free
- Not guarding move assignment against self-move
- Believing move operations are generated automatically once copy operations are user-defined (they are not)
- Omitting noexcept on move operations, preventing containers from using them safely
Best Answer (HR Friendly)
“The Rule of Five builds on the Rule of Three by adding move semantics. Alongside the destructor and copy operations, I also define a move constructor and move assignment operator so that when an object is being discarded anyway, its resource can just be transferred cheaply to the new object instead of being expensively duplicated. This makes code that returns or reallocates such objects much faster.”
Code Example
class ResourceHandle {
private int[] buffer;
ResourceHandle(int size) {
this.buffer = new int[size];
}
// Copy: deep duplication (Rule of Three)
ResourceHandle(ResourceHandle other) {
this.buffer = other.buffer.clone();
}
// Move-style transfer (Rule of Five concept): steal and null the source
static ResourceHandle moveFrom(ResourceHandle source) {
ResourceHandle moved = new ResourceHandle(0);
moved.buffer = source.buffer; // steal the reference, no copy
source.buffer = null; // leave source empty and safely destructible
return moved;
}
void release() {
buffer = null;
}
}
ResourceHandle a = new ResourceHandle(1000);
ResourceHandle moved = ResourceHandle.moveFrom(a); // cheap transfer, no deep copy
a.release(); // safe: a no longer owns the bufferFollow-up Questions
- What is the difference between a move constructor and a copy constructor?
- Why should move operations be marked noexcept?
- What state should an object be left in after being moved from?
- How does std::vector benefit from a class implementing move semantics?
MCQ Practice
1. The Rule of Five adds which two operations to the Rule of Three?
The Rule of Five adds the move constructor and move assignment operator for efficient resource transfer.
2. A move constructor typically accepts a parameter of what type?
Move constructors bind to rvalue references, allowing them to steal resources from expiring temporaries.
3. After a move constructor steals a resource, the source object should be left?
The source must be left valid but empty so its destructor does not double-free the transferred resource.
Flash Cards
Rule of Five in one line? — Rule of Three plus move constructor and move assignment operator.
What does a move do? — Transfers resource ownership cheaply instead of deep-copying it.
What must move operations do to the source? — Leave it in a valid, empty, safely destructible state.
Why mark moves noexcept? — So containers like vector can safely prefer moving over copying during reallocation.