The Rule of Five in C++ | Explained - CodersLegacy (2024)

The Rule of Five is a programming concept brought about in C++11. It originates from the Rule of Three, where the introduction of Move Semantics in C++11, caused the Rule Of Three to expand and become the Rule Of Five.

Before we talk about the Rule of Five however, we will briefly talk about the Rule Of Three to understand it’s base.

What is the Rule of Three?

The Rule of Three states, that if a Class explicitly defines any of the following special member functions:

  1. Destructor
  2. Copy Constructor
  3. Copy Assignment Constructor

Then it is required to define the other two along with it. In short, if a Class explicitly defines the Destructor, then it should explicitly define the Copy Constructor and the Copy Assignment Constructor too..

By “explicitly” defined, we mean when the User himself defines the Member Function. Don’t forget that there are already default implementations of these member functions that exist. But these default versions only perform the very basics, and not suitable for many scenarios.

An example of where the Rule Of Three comes into play, is when we are dealing with Dynamic Memory in a Class. The Class must create the Destructor in order to free up that memory. It must also create the Copy Constructor and Copy Assignment Constructor to avoid running into the Shallow Copy issue. (The default implementation will only copy the pointer to the memory, not the actual contents. This results in both objects pointing to the same memory).

The Rule of Five in C++

Instead of just three Special Member functions, the Rule Of Five now encompasses a total of Five Special Member Functions that need to be defined in the event that any of them is required to be defined.

  1. Destructor
  2. Copy Constructor
  3. Copy Assignment Operator
  4. Move Constructor
  5. Move Assignment Operator

The first three are the same as the Rule Of Three, and have the same reasoning. In the next discussion we will discuss the two new additions.

Move Semantics

The two new additions are the Move Constructor and Move Assignment Constructor, which were introduced in C++11 (also known as Move Semantics). This concept was introduced to deal with the inefficiency introduced by Copy Constructors when dealing with memory.

To understood this concept, let’s imagine a situation where we have made the following assumptions:

  1. Let’s assume we have some memory (e.g: A custom String Class) that we have allocated in the main() function.
  2. We also have a Class A, to which we want to copy over this memory.
  3. We don’t need this memory in main(), and the only purpose of creating this was to copy it over into Class A.

The code for this looks something like this:

int main() { ClassA objA = ClassA( String("Hello World");}

The problem with the above approach, is that we will end up with two instances of the same memory. The string “Hello World” will first be allocated in the main() function, and then copied into Class A. When Class A copies it, it will create new memory for the String. This is the nature of Copy Constructors, which looks something like this:

 String(const String& str) { // Copy Constructor cout << "Copy Constructor Called\n"; _size = str._size; _data = new char[_size]; memcpy(_data, str._data, _size); }

Now this is a problem, as memory is allocated twice, and also deallocated twice. Just to reiterate, the first Allocation takes place in the main function, and the second takes place in the Copy Constructor of the Class A when creating the new object.

Move Constructors on the other hand, actually “move” the memory, instead of copying it. See the example in the next section on how Move Constructors are actually implemented.

It is important to note, that Move Constructors are not a replacement for Copy Constructors. If you need an actual Copy of the memory, then you will need to use a Copy Constructor. Only when we literally want to “move” the memory (i.e. Assumption number 3 that we made), do we use Move Constructors.

Rule of Five – Example

Let’s take a look at an actual real-life example, regarding the creation of a String Class in C++. This example follows the Rule of Five, and has all Five Special Member Functions available in it. If you run the following code, you will also notice several of these Member Functions being used.

#include <iostream>#include <cstring>using namespace std;class String { char * _data; int _size;public: String(const char* data) { // Constructor cout << "Created" << endl; _size = strlen(data); _data = new char[_size]; memcpy(_data, data, _size); } String(String&& str) { // Move Constructor cout << "Move Constructor Called" << endl; _size = str._size; _data = str._data; str._data = nullptr; } String& operator=(String&& str) { // Move Assignment Constructor if (this != &str) { delete[] _data; _data = str._data; str._data = nullptr; } return *this; } String& operator=(const String& str) { if (this == &str) return *this; delete[] _data; _data = NULL; _size = str._size; _data = new char[_size]; memcpy(_data, str._data, _size); return *this; } String(const String& str) { // Copy Constructor cout << "Copy Constructor Called\n"; _size = str._size; _data = new char[_size]; memcpy(_data, str._data, _size); } ~String() { // Destructor cout << "Destructor Called\n"; delete[] _data; } void Print() const { for (size_t i = 0; i < _size; i++) cout << _data[i]; cout << endl; }};class Person { String _name;public: Person(const String& s) : _name(s) { } Person(String&& s) : _name(std::move(s)) { } void Print) { _name.Print(); }};int main() { Person person(String("CodersLegacy")); person.Print();}

References

The above example (and by extension, the Rule of Five) relies heavily on the concept of Move Semantics. If you wish to learn more about this concept, check out our dedicated tutorial on Move Semantics in C++.

If you want to know more about the , refer to our dedicated tutorial on the topic.

This marks the end of the “Rule of Five in C++” Tutorial. Any suggestions or contributions for CodersLegacy are more than welcome. Questions regarding the tutorial content can be asked in the comments section.

The Rule of Five in C++ | Explained - CodersLegacy (2024)

References

Top Articles
Latest Posts
Article information

Author: Arline Emard IV

Last Updated:

Views: 5354

Rating: 4.1 / 5 (72 voted)

Reviews: 87% of readers found this page helpful

Author information

Name: Arline Emard IV

Birthday: 1996-07-10

Address: 8912 Hintz Shore, West Louie, AZ 69363-0747

Phone: +13454700762376

Job: Administration Technician

Hobby: Paintball, Horseback riding, Cycling, Running, Macrame, Playing musical instruments, Soapmaking

Introduction: My name is Arline Emard IV, I am a cheerful, gorgeous, colorful, joyous, excited, super, inquisitive person who loves writing and wants to share my knowledge and understanding with you.