# C++ Rule of Five

## Introduction

C++ “rule of five” is the rules of thumb in modern C++ for the building of exception-safe code and for formalizing rules on resource management.

In this blog post, I would like to discuss about the “rule of three” for classic C++, “rule of five” for modern C++, and their logics behind.

## Rule of Three

The classic C++ has a “rule of three”. If a class requires a user-defined destructor, a user-defined copy constructor, or a user-defined copy assignment operator, it almost certainly requires all three.

The logic behind the “rule of three” is that if the user ever wants to implement a user-defined destructor, a user-defined copy constructor, or a user-defined copy assignment operator, rather than uses the implicit destructor, copy constructor, and copy assignment operator, the object of this class usually has raw pointers pointing to the data on the heap. To handle the data on the heap, user-defined destructor, user-defined copy constructor, and user-defined copy assignment operator are all required.

However, the “rule of three” is not usually enforced by the compiler, and the compiler will not even throw warning if the “rule of three” was not followed in the code. For example, if we intentionally comment out the user-defined destructor and the user-defined copy constructor from the rule_of_three class defined in the “The Rule of Three/Five/Zero”.

The GCC compiler successfully compiled the code without even throwing a warning.

Of course, this program is problematic and will encounter problems during runtime.

## Rule of Five

Move semantics have been introduced to C++ since C++11. As a result of that the “rule of three” has been extended to “rule of five”. If a class requires a user-defined destructor, a user-defined copy constructor, a user-defined copy assignment operator, a user-defined move constructor, a user-defined move assignment operator, it almost certainly requires all five.

The logic behind the “rule of five” is exactly the same as “rule of three”. It is all about the resource management.

The “rule of five” has been enforced by the compiler to some extent. Since C++11, the implicitly-declared copy constructor and copy assignment will be deleted if the class has a user-defined move constructor or move assignment operator. For example, a CustomString class that follows the “rule of five” has been implemented.

If the copy constructor and the copy assignment were commented out,

The implicitly-declared copy constructor and copy assignment have been indeed deleted as expected.

It should also be noticed that the program still compiles and runs fine if the move constructor and the move assignment have been deleted.

This is due to C++11 has to be compatible with the classic C++ which does not have move semantics. Because the rvalues std::move(string1) can be converted to const lvalue, copy constructor and copy assignment were called when the rvalue is encountered if there is no move constructor and move assignment overloading.

Lei Mao

04-17-2022

04-17-2022