Rule of Five
Rule of Five
Rule of Five
Prerequisites
1. What is Rule of Five
The Rule of Five states:
If a class manages resources and defines one of these:
- destructor
- copy constructor
- copy assignment operator
Then it should also define:
- move constructor
- move assignment operator
If your class manages resources, you should explicitly define all five special member functions.
2. Why Do We Need It?
C++ classes often manage:
- dynamic memory (
new/delete) - file handles
- sockets
- mutexes
Use when:
- managing raw resources
- using
new/delete - handling ownership manually
❌ Default Behavior Problem
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A
{
int* data;
public:
A(int v)
{
data = new int(v);
}
~A()
{
delete data;
}
};
Issue
1
2
A a1(10);
A a2 = a1; // shallow copy
- Both objects point to the same memory
- double delete → crash
3. The Five Functions
3-1. Destructor
1
2
3
4
~A()
{
delete data;
}
releases resource
3-2. Copy Constructor
1
2
3
4
A(const A& other)
{
data = new int(*other.data);
}
deep copy
3-3. Copy Assignment Operator
1
2
3
4
5
6
7
8
9
A& operator=(const A& other)
{
if (this != &other)
{
delete data;
data = new int(*other.data);
}
return *this;
}
3-4. Move Constructor
1
2
3
4
5
A(A&& other) noexcept
{
data = other.data;
other.data = nullptr;
}
transfers ownership (no copy)
3-5. Move Assignment Operator
1
2
3
4
5
6
7
8
9
10
11
A& operator=(A&& other) noexcept
{
if (this != &other)
{
delete data;
data = other.data;
other.data = nullptr;
}
return *this;
}
4. Performance Perspective
❌ Copy
1
alloc → copy → slow
✔️ Move
1
pointer transfer → fast
Move avoids:
- allocation
- deep copy
- expensive operations
4-1. Stable Design
❌ Missing self-assignment check
1
if (this != &other)
❌ Not using noexcept
1
A(A&& other) noexcept;
required for STL optimizations
5. Full Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class A
{
int* data;
public:
A(int v) : data(new int(v)) {}
~A()
{
delete data;
}
A(const A& other)
{
data = new int(*other.data);
}
A& operator=(const A& other)
{
if (this != &other)
{
delete data;
data = new int(*other.data);
}
return *this;
}
A(A&& other) noexcept
{
data = other.data;
other.data = nullptr;
}
A& operator=(A&& other) noexcept
{
if (this != &other)
{
delete data;
data = other.data;
other.data = nullptr;
}
return *this;
}
};
6. Rule of Zero / One / Three / Five
| Rule | Meaning | Focus | When to Use | Key Functions |
|---|---|---|---|---|
| Rule of Zero | Do not define any special member functions | No manual resource management | Use STL containers / smart pointers | None |
| Rule of One | One class manages one resource (RAII principle) | Single responsibility for a resource | Designing simple resource wrappers | Typically destructor (and possibly others) |
| Rule of Three | If one is defined, define all three | Safe copying of resources | When managing raw resources (C++98 style) | Destructor, Copy Constructor, Copy Assignment |
| Rule of Five | Rule of Three + move semantics | Efficient resource transfer | When performance matters (C++11+) | + Move Constructor, Move Assignment |
This post is licensed under CC BY 4.0 by the author.