The "Rule of Five" is a guideline for efficient and bug-free programming in C++. The Rule of Five states that,
If any of the below functions is defined for a class, then it is better to define all of them.
It includes the following functions of a class:
- Destructor
- Copy Constructor
- Copy Assignment Operator
- Move Constructor
- Move Assignment Operator
The Rule of Big Five is an extension of the Rule of Three to include move semantics. The Rule of Three, consists of a destructor, copy constructor, and, copy assignment operator, use all these three functions when you are dealing with dynamically allocated resources Whereas The Rule of Five includes two more functions i.e. move constructor and move assignment operator.
Need for Rule of Five in C++
In C++ "The Rule of Big Five" is needed to properly manage the resources and efficiently handle objects. Following are the important reasons why we should use the Rule of the Big Five:
- Assume that you have some dynamically allocated resources in the object and you copy them using shallow copy. This will lead to problems like segmentation faults when the source object is destroyed. Similar thing will happen with copy assignment, move constructor and move assignment operator.
- By implementing Rule of Big Five properly we can make sure that there are no resource leaks. This can be achieved by ensuring that all the dynamically allocated memory or any other resources are released appropriately.
Let's discuss each of the five special member functions that a class should define in detail
1. Destructor
The Destructor is used for removing/freeing up all the resources that an object has taken throughout its lifetime.With the help of this destructor, we make sure that any resources taken by objects are properly released before the object is no longer in scope.
Syntax
class ClassName {
public:
// Destructor
~ClassName() {
// releasing allocated memory
// Make sure to add the necessary code to release any resources you've acquired, such as dynamic memory or file handles.
}
};
2. Copy Constructor
Copy Constructor is used to make a new object by copying an existing object. Copy constructor is invoked when we use it to pass an object by value or when we make a copy explicitly. mainly we use copy constructor to replicate an already existing object.
Syntax
class ClassName {
public:
// Copy Constructor
ClassName(const ClassName& other) {
// Here's the code for the copy constructor, which performs a deep copy of the resources.
}
};
3. Copy Assignment Operator
Copy Assignment Operator is a special type of function that takes care of assigning the data of one object to another object. It gets called when you use this assignment operator (=) between objects.
Syntax
class ClassName {
public:
// Copy Assignment Operator
ClassName& operator=(const ClassName& other) {
if (this != &other) {
// generate a deep copy of resources
}
return *this;
}
};
4. Move Constructor
Move Constructor is one of the member functions that is used to transfer the ownership of resources from one object to another. This job can easily be done by this move constructor by using a temporary object called rvalue
Syntax
class ClassName {
public:
// Move Constructor
ClassName(ClassName&& other) noexcept //“noexcept” is not a function name but a specifier in C++, does not throw any exceptions
{
// Here's the code for the move constructor,
// The transfer of ownership of resources.
}
};
Explanation: In the above syntax, “noexcept” is used to indicate that the given function, like the move constructor in this case, does not throw any kind of exceptions. The move constructor is specifically designed to handle temporary objects and it requires an rvalue reference (ClassName&& other) as a parameter.
5. Move Assignment Operator
The Move Assignment Operator is comparable to the Move Constructor. It is used when an existing object is assigned the value of an rvalue. It is activated when you use the assignment operator (=) to assign the data of a temporary object(value) to an existing object.
Syntax
class ClassName {
public:
// Move Assignment Operator
ClassName& operator=(ClassName&& other) noexcept {
if (this != &other) {
//code here,
//transfer ownership of resources.
}
return *this;
}
};
Example
The below example demonstrates the use of all five member functions: Destructor, Copy Constructor, Copy Assignment Operator, Move Constructor, and Move Assignment Operator.
C++
// C++ program to demonstrate all 5 member functions
// :Destructor, Copy Constructor, Copy Assignment Operator,
// Move Constructor, and Move Assignment Operator.
#include <iostream>
#include <utility> // for using move
using namespace std;
class ResourceManager {
private:
int* data;
size_t size;
public:
// default constructor
ResourceManager(size_t sz = 0)
: data(new int[sz])
, size(sz)
{
cout << "Default Constructor is called" << endl;
}
// Destructor
~ResourceManager()
{
delete[] data;
cout << "Destructor is called" << endl;
}
// Copy Constructor
ResourceManager(const ResourceManager& other)
: data(new int[other.size])
, size(other.size)
{
copy(other.data, other.data + other.size, data);
cout << "Copy Constructor is called" << endl;
}
// Copy Assignment Operator
ResourceManager& operator=(const ResourceManager& other)
{
if (this != &other) {
delete[] data;
data = new int[other.size];
size = other.size;
copy(other.data, other.data + other.size, data);
}
cout << "Copy Assignment Operator is called"
<< endl;
return *this;
}
// Move Constructor
ResourceManager(ResourceManager&& other) noexcept
: data(other.data),
size(other.size)
{
other.data = nullptr;
other.size = 0;
cout << "Move Constructor" << endl;
}
// Move Assignment Operator
ResourceManager&
operator=(ResourceManager&& other) noexcept
{
if (this != &other) {
delete[] data;
data = other.data;
size = other.size;
other.data = nullptr;
other.size = 0;
}
cout << "Move Assignment Operator" << endl;
return *this;
}
};
int main()
{
// Creating an object using default constructor
ResourceManager obj1(5);
// Creating an object using Copy constructor
ResourceManager obj2 = obj1;
// Creating an object using Copy assignment operator
ResourceManager obj3;
obj3 = obj1;
// Creating an object using Move constructor
ResourceManager obj4 = move(obj1);
// Creating an object using Move assignment operator
ResourceManager obj5;
obj5 = move(obj2);
return 0;
}
Output
Default Constructor is called
Copy Constructor is called
Default Constructor is called
Copy Assignment Operator is called
Move Constructor
Default Constructor is called
Move Assignment Operator
Destructor is called
Destructor is called
Destructor is called
Destructor is called
Destructor is called
Conclusion
In C++ "The Rule of Big Five" is used to ensure that the memory is properly handled i.e. memory allocation and deallocation is done properly and also resource management. It is an extension of Rule of Three. This rule says that we should use or try to use all the five functions (Destructor, Copy Constructor, Copy Assignment Operator, Move Constructor, and Move Assignment Operator) even if initially we require only one so that we can achieve application optimization, less bugs, efficient code and manage the resources efficiently.
Similar Reads
sort() in C++ STL In C++, sort() is a built-in function used to sort the given range in desired order. It provides a simple and efficient way to sort the data in C++, but it only works on data structures that provide random access to its elements such as vectors and arrays.Let's take a look at an example:C++#include
4 min read
Modifiers for Vector in C++ STL Click here for Set 1 of Vectors. Modifiers 1.1 assign(input_iterator first, input_iterator last) - Assigns new content to vector and resize 1.2 assign(size_type n, const value_type g) - Assigns new content to vector and resize CPP #include <iostream> #include <vector> using namespace std
5 min read
Order of Evaluation in C++17 In C++ programming, the order of evaluation of expressions can have a significant impact on the behavior and correctness of the code. C++17 introduced changes to the order of evaluation rules, providing clearer guidelines and improving consistency across different compilers. In this article, we will
4 min read
Array of Vectors in C++ STL Prerequisite: Arrays in C++, Vector in C++ STL An array is a collection of items stored at contiguous memory locations. It is to store multiple items of the same type together. This makes it easier to get access to the elements stored in it by the position of each element. Vectors are known as dynam
3 min read
std::distance in C++ The std::distance() in C++ STL is a built-in function used to calculate the number of elements between two iterators. It is defined inside <iterator> header file. In this article, we will learn about the std::distance function in C++ with examples.Example:C++// C++ Program to illustrate the us
5 min read
Multiset of Vectors in C++ with Examples What is Multiset? A multiset in C++ is an associative container that can hold a number of elements in a specific order. Unlike a set, a multiset can hold multiple copies of the same element. Functions associated with a multiset: begin(): Returns an iterator to the first element in the multiset.end()
4 min read
iota() in C++ In C++, iota() is a library function used to fill a range of elements with increasing values starting from the given initial value. It assigns the starting value to the first element and then increments it once for the next element and so on.Let's take a look at an example:C++#include <bits/stdc+
3 min read
valarray pow() function in C++ The pow() function is defined in valarray header file. This function returns a valarray containing the results of the power operation on all the elements, in the same order. Syntax: pow(varr, n); Parameter: varr: This represents the valarray object.n: It represents a exponent value. Returns: This fu
2 min read
Literals in C++ In C++ programming language, literals are fundamental elements used to represent fixed values. These values can include numbers, characters, strings, and more. They are generally present as the right operand in the assignment operation.Let's take a look at an example:C++#include <iostream> usi
6 min read
fill() function in C++ STL with examples The fill() function in C++ STL is used to fill some default value in a container. The fill() function can also be used to fill values in a range in the container. It accepts two iterators begin and end and fills a value in the container starting from position pointed by begin and just before the pos
2 min read