What is the Rule of Three in C++?
Learn the C++ Rule of Three — destructor, copy constructor and copy assignment — with examples and how it connects to the Rule of Five.
Expected Interview Answer
The Rule of Three states that if a C++ class defines any one of a custom destructor, copy constructor, or copy assignment operator, it almost certainly needs to define all three, because the presence of one signals the class manages a resource that the compiler-generated defaults would handle incorrectly.
When a class owns a raw resource such as heap memory, a file handle, or a socket, the compiler-generated copy constructor and copy assignment operator perform a shallow, member-wise copy. That shallow copy duplicates the pointer, not the underlying resource, so two objects end up owning the same resource. When either object is destroyed, its destructor frees the resource, and the other object is left holding a dangling pointer, leading to a double free or use-after-free. Writing a custom destructor to release the resource properly is the first sign that ownership is non-trivial, and it therefore should trigger writing matching copy operations that perform a deep copy so each object owns an independent resource. Modern guidance extends this to the Rule of Five by adding a move constructor and move assignment for efficient transfer instead of copying.
- Prevents double-free and use-after-free bugs from shallow copies
- Makes resource ownership explicit and consistent
- Forces deliberate design of copy semantics for resource-owning types
- Lays the foundation for the Rule of Five and safe move semantics
AI Mentor Explanation
When a team custom-builds its own dedicated practice net, a resource nobody else shares, it must also define exactly how that net is duplicated for a second ground and how it is torn down when no longer needed. If only the teardown crew is briefed but nobody defines correct duplication for another venue, the second venue ends up referencing the exact same physical net structure, and tearing down one destroys both. The Rule of Three says once you write custom teardown logic for an owned resource, you must also write matching, correct duplication logic, not rely on a generic copy.
Step-by-Step Explanation
Step 1
Recognize resource ownership
If a class manages a raw pointer, handle, or other non-trivially-copyable resource, it is a Rule of Three candidate.
Step 2
Write the destructor
Release the owned resource (delete, close, free) in the destructor.
Step 3
Write the copy constructor
Perform a deep copy so the new object owns an independent resource, not a shared pointer.
Step 4
Write the copy assignment operator
Release the current resource, then deep-copy the source, guarding against self-assignment.
What Interviewer Expects
- Correct explanation of why shallow-copy defaults break resource-owning classes
- Awareness that defining one of the three should prompt defining all three
- Mention of double-free or use-after-free as the concrete failure mode
- Connection to the modern Rule of Five (move constructor and move assignment)
Common Mistakes
- Only writing a custom destructor and leaving the compiler-generated copy operations in place
- Forgetting a self-assignment check inside copy assignment
- Confusing the Rule of Three with the Rule of Zero, which avoids owning raw resources entirely
- Not knowing the Rule of Five extends this with move semantics
Best Answer (HR Friendly)
“The Rule of Three means that if I write a custom destructor for a class because it owns a resource like heap memory, I also need to write a custom copy constructor and copy assignment operator for it. Otherwise the compiler’s default shallow copy will duplicate the pointer, not the resource, and I will end up with two objects trying to free the same memory, which is a classic double-free bug.”
Code Example
class ResourceHandle {
private int[] buffer;
ResourceHandle(int size) {
this.buffer = new int[size];
}
// Deep-copy equivalent of a C++ copy constructor
ResourceHandle(ResourceHandle other) {
this.buffer = other.buffer.clone();
}
// Equivalent of a C++ destructor releasing an owned resource
void release() {
buffer = null;
}
}
ResourceHandle original = new ResourceHandle(10);
ResourceHandle copy = new ResourceHandle(original); // independent deep copy
original.release();
// copy remains valid because it owns its own buffer, not the original'sFollow-up Questions
- What failure happens if you only define a destructor without copy operations?
- How does the Rule of Five extend the Rule of Three?
- What is the Rule of Zero and when does it apply instead?
- How do you guard a copy assignment operator against self-assignment?
MCQ Practice
1. The Rule of Three applies primarily to classes that?
The rule addresses classes managing raw resources where default shallow copies break ownership.
2. What happens with the compiler-generated copy constructor on a resource-owning class?
The default copy constructor copies members (including pointers) shallowly, duplicating the pointer, not the resource.
3. What modern extension adds move semantics to the Rule of Three?
The Rule of Five adds a move constructor and move assignment operator alongside the original three.
Flash Cards
Rule of Three in one line? — If you define one of destructor, copy constructor, or copy assignment, define all three.
Why does it matter? — Default shallow copies duplicate pointers, causing double-free or use-after-free bugs.
What extends it? — The Rule of Five, adding move constructor and move assignment.
Alternative approach? — The Rule of Zero: avoid owning raw resources directly, use RAII wrappers like smart pointers instead.