Skip to main content

Copy Constructors and Rule of Three

intermediate30 min readLesson 88 of 204

Deep vs member-wise copy, self-assignment, allocate-then-release, and why the rule exists.

When an object is copied (by value, from a container growth, pass-by-value), C++ uses the copy constructor; on assignment, the copy assignment operator. The compiler generates member-wise copies by default โ€” correct for value members, deeply wrong for raw owning pointers.

#include <cstring>
#include <iostream>

class Buffer {
public:
    explicit Buffer(std::size_t n) : size_{n}, data_{new char[n]{}} {}
    ~Buffer() { delete[] data_; }

    Buffer(const Buffer& other)                       // copy ctor: deep copy
        : size_{other.size_}, data_{new char[other.size_]} {
        std::memcpy(data_, other.data_, size_);
    }

    Buffer& operator=(const Buffer& other) {           // copy assign
        if (this == &other) return *this;              // self-assignment guard
        char* fresh = new char[other.size_];           // allocate FIRST
        std::memcpy(fresh, other.data_, other.size_);
        delete[] data_;                                // only then release
        data_ = fresh;
        size_ = other.size_;
        return *this;
    }

    std::size_t size() const { return size_; }
    char& at(std::size_t i) { return data_[i]; }

private:
    std::size_t size_;
    char* data_;
};

Rule of Three

If you write any of: destructor, copy constructor, copy assignment โ€” you almost certainly need all three. A destructor signals the type owns a resource; default member-wise copying then creates two owners of one resource (double-free), which is the classic crash.

The copy-and-swap alternative

Buffer& operator=(Buffer other) { swap(*this, other); return *this; } handles self-assignment, gives the strong exception guarantee, and is hard to get wrong โ€” at the cost of one extra copy.

Now practice

Rule of Three and move semanticsA deep-copying Blob with correct assignment, and counters that prove moves happen.2 challenges ยท ยท ~40 min