Skip to content
  • Rule of 0 / 3 / 5 · C++

Rule of 0 / 3 / 5

LearnViaNotes @learnvianotes· 2 min read

If a class needs a custom destructor, copy or move operation, it almost certainly needs all of them. Better still: design so it needs none.

The rules

Rule of Zero in practice

C++
#include <iostream>
#include <memory>
#include <string>
#include <vector>

class Document {                                    // no destructor, no copy/move code
    std::string title_;
    std::vector<std::string> lines_;
    std::unique_ptr<int> cache_ = std::make_unique<int>(0);   // move-only member
public:
    explicit Document(std::string t) : title_(std::move(t)) {}
    void add(std::string line) { lines_.push_back(std::move(line)); }
    std::size_t size() const { return lines_.size(); }
};

int main() {
    Document d("notes");
    d.add("line 1");
    Document moved = std::move(d);   // compiler-generated move: correct automatically
    std::cout << moved.size() << ' ' << d.size() << '\n';
    // Document copy = moved;        // error: unique_ptr member makes it move-only
}
Output
1 0

Rule of Five, spelled out

C++ — all five special members
#include <utility>

class Handle {
    int* res_ = nullptr;
public:
    explicit Handle(int v) : res_(new int(v)) {}
    ~Handle() { delete res_; }                                                   // 1 destructor
    Handle(const Handle& o) : res_(o.res_ ? new int(*o.res_) : nullptr) {}       // 2 copy ctor
    Handle& operator=(const Handle& o) {                                          // 3 copy assign
        Handle tmp(o);
        std::swap(res_, tmp.res_);
        return *this;
    }
    Handle(Handle&& o) noexcept : res_(std::exchange(o.res_, nullptr)) {}         // 4 move ctor
    Handle& operator=(Handle&& o) noexcept {                                      // 5 move assign
        std::swap(res_, o.res_);                                                  //   old value dies with o
        return *this;
    }
};

What declaring one member suppresses

You declare…Default ctorCopy opsMove ops
NothingGeneratedGeneratedGenerated
Any constructorNot generatedGeneratedGenerated
DestructorGeneratedGenerated (deprecated)Not generated → moves become copies
Copy ctor or copy assignment—The other is generated (deprecated)Not generated
Move ctor or move assignment—DeletedThe other is not generated

Explain the Rule of Zero.

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report