Rule of five

The “Rule of Five” in C++ refers to a guideline for implementing the five special member functions in a class when managing resources. These special member functions are:

  1. Destructor
  2. Copy constructor
  3. Move constructor
  4. Copy assignment operator
  5. Move assignment operator

The Rule of Five suggests that if you need to explicitly define or customize any of these special member functions, you should typically define or customize all five of them together to ensure proper resource management and prevent issues like resource leaks or double deletions.

Let’s look at an example to understand how the Rule of Five works:

#include <iostream>

class Resource {
private:
    int* data;
    int size;

public:
    // Constructor
    Resource(int s) : size(s) {
        data = new int[size];
        for (int i = 0; i < size; ++i) {
            data[i] = i;
        }
        std::cout << "Resource constructed." << std::endl;
    }

    // Destructor
    ~Resource() {
        delete[] data;
        std::cout << "Resource destroyed." << std::endl;
    }

    // Copy constructor
    Resource(const Resource& other) : size(other.size) {
        data = new int[size];
        for (int i = 0; i < size; ++i) {
            data[i] = other.data[i];
        }
        std::cout << "Resource copied." << std::endl;
    }

    // Move constructor
    Resource(Resource&& other) noexcept : data(other.data), size(other.size) {
        other.data = nullptr;
        other.size = 0;
        std::cout << "Resource moved." << std::endl;
    }

    // Copy assignment operator
    Resource& operator=(const Resource& other) {
        if (this != &other) {
            delete[] data;
            size = other.size;
            data = new int[size];
            for (int i = 0; i < size; ++i) {
                data[i] = other.data[i];
            }
        }
        std::cout << "Resource copied (assignment)." << std::endl;
        return *this;
    }

    // Move assignment operator
    Resource& operator=(Resource&& other) noexcept {
        if (this != &other) {
            delete[] data;
            data = other.data;
            size = other.size;
            other.data = nullptr;
            other.size = 0;
        }
        std::cout << "Resource moved (assignment)." << std::endl;
        return *this;
    }
};

int main() {
    Resource r1(5);
    Resource r2(r1);  // Copy constructor
    Resource r3(std::move(r1));  // Move constructor

    r1 = r2;  // Copy assignment operator
    r2 = std::move(r3);  // Move assignment operator

    return 0;
}

In this example, we have a Resource class that manages a dynamically allocated array of integers. The constructor initializes the data array, and the destructor releases the memory when the object is destroyed. The copy constructor, move constructor, copy assignment operator, and move assignment operator are also implemented.

In the main() function, we create Resource objects r1, r2, and r3 using different constructors and assignment operations. By implementing all five special member functions according to the Rule of Five, we ensure that resources are properly managed and transferred between objects. The output will show messages indicating the construction, copying, moving, and destruction of the Resource objects.

It’s important to note that with C++11 and later, the Rule of Five is often replaced or supplemented by the Rule of Zero, which recommends relying on smart pointers and standard library containers to manage resources whenever possible, reducing the need for explicit resource management.

Leave a Reply

Your email address will not be published. Required fields are marked *