The "Rule of Three" is a guideline in C++ that states that if a class defines any of the following three special member functions, it should also define the other two:
Copy constructor: A special constructor that creates a new object that is a copy of an existing object of the same class.
Copy assignment operator: A special member function that copies the contents of one object into another object of the same class.
Destructor: A special member function that is called when an object of the class is destroyed, and is used to clean up any resources that the object has allocated during its lifetime.
The reason for the "Rule of Three" is to ensure that the class behaves correctly in all situations, and to avoid memory leaks or other problems that can arise from inconsistent memory management.
For example, if a class has a dynamically allocated memory resource that is managed by the constructor and destructor, it is important to define the copy constructor and copy assignment operator to properly handle copying the memory resource from one object to another. If these functions are not defined, the default implementations provided by the compiler may simply copy the pointer to the memory resource, resulting in two objects pointing to the same memory location. This can cause problems if one object is destroyed or modified, leaving the other object with a dangling pointer or invalid data.
Here is an example of a class that follows the Rule of Three:
class MyClass { public: MyClass(); // Default constructor MyClass(const MyClass& other); // Copy constructor MyClass& operator=(MyClass pObj); // Copy assignment operator ~MyClass(); // Destructor private: int* data; int size; }; MyClass::MyClass() { size = 10; data = new int[size]; } MyClass::MyClass(const MyClass& other) { size = other.size; data = new int[size]; for (int i = 0; i < size; i++) { data[i] = other.data[i]; } } MyClass& MyClass::operator=(MyClass rhs) { swap(size, rhs.size); swap(data, rhs.data); return *this; } MyClass::~MyClass() { delete[] data; } int main() { MyClass obj1; MyClass obj2 = obj1; // Use copy constructor MyClass obj3; obj3 = obj2; // Use copy assignment operator return 0; }
In this example, the MyClass
class has a dynamically allocated array data
that is managed by the constructor and destructor. The copy constructor and copy assignment operator have been defined to create deep copies of the data
array, and the destructor deallocates the memory when the object is destroyed.
By following the Rule of Three and defining all three special member functions, the MyClass
class can be used safely and consistently in all situations, and avoids any issues with memory management or data consistency.
The Rule of Five
The Rule of Five is an extension of the Rule of Three in C++11 and later versions. It applies to classes that manage resources, such as memory or file handles. The Rule of Five states that if a class defines any of the following special member functions, it should define all five:
Destructor
Copy constructor
Copy assignment operator
Move constructor
Move assignment operator
The reason behind this rule is to ensure correct resource management and avoid issues like memory leaks, dangling pointers, or double deletion. The move constructor and move assignment operator were introduced in C++11 to enable efficient transfer of resources between objects, which is particularly useful for objects that manage dynamically allocated memory.
Move constructor: A move constructor is used to create a new object by transferring the resources from an existing object (called an rvalue). It takes an rvalue reference (&&) to an object of the same class as its parameter.
Move assignment operator: The move assignment operator is used to transfer the resources from one object (rvalue) to another object of the same class. It is typically implemented as an overloaded assignment operator (operator=) that takes an rvalue reference (&&) to an object of the same class.