assignment-operator c++ c++-faq copy-constructor rule-of-three

What is The Rule of Three?


  • What does copying an object mean?
  • What are the copy constructor and the copy assignment operator?
  • When do I need to declare them myself?
  • How can I prevent my objects from being copied?


  • 62

    Please read this whole thread and the c++-faq tag wiki before you vote to close.

    – sbi

    Nov 13, 2010 at 14:06

  • 17

    @Binary: At least take the time to read the comment discussion before you cast a vote. The text used to be much simpler, but Fred was asked to expand on it. Also, while that’s four questions grammatically, it really is just one question with several aspects to it. (If you disagree to that, then prove your POV by answering each of those questions on its own and let us vote on the results.)

    – sbi

    Nov 15, 2010 at 23:02

  • 6

    Related: The Law of The Big Two

    Jun 27, 2011 at 16:39

  • 6

    Keep in mind that, as of C++11, I think this has been upgraded to the rule of five, or something like that.

    – paxdiablo

    Aug 19, 2015 at 10:31

  • 2

    @paxdiablo The Rule of Zero to be exact.

    – rubenvb

    Sep 25, 2015 at 11:08



C++ treats variables of user-defined types with value semantics.
This means that objects are implicitly copied in various contexts,
and we should understand what “copying an object” actually means.

Let us consider a simple example:

class person
    std::string name;
    int age;


    person(const std::string& name, int age) : name(name), age(age)

int main()
    person a("Bjarne Stroustrup", 60);
    person b(a);   // What happens here?
    b = a;         // And here?

(If you are puzzled by the name(name), age(age) part,
this is called a member initializer list.)

Special member functions

What does it mean to copy a person object?
The main function shows two distinct copying scenarios.
The initialization person b(a); is performed by the copy constructor.
Its job is to construct a fresh object based on the state of an existing object.
The assignment b = a is performed by the copy assignment operator.
Its job is generally a little more complicated,
because the target object is already in some valid state that needs to be dealt with.

Since we declared neither the copy constructor nor the assignment operator (nor the destructor) ourselves,
these are implicitly defined for us. Quote from the standard:

The […] copy constructor and copy assignment operator, […] and destructor are special member functions.
[ Note: The implementation will implicitly declare these member functions
for some class types when the program does not explicitly declare them.

The implementation will implicitly define them if they are used. […] end note ]
[n3126.pdf section 12 §1]

By default, copying an object means copying its members:

The implicitly-defined copy constructor for a non-union class X performs a memberwise copy of its subobjects.
[n3126.pdf section 12.8 §16]

The implicitly-defined copy assignment operator for a non-union class X performs memberwise copy assignment
of its subobjects.
[n3126.pdf section 12.8 §30]

Implicit definitions

The implicitly-defined special member functions for person look like this:

// 1. copy constructor
person(const person& that) : name(, age(that.age)

// 2. copy assignment operator
person& operator=(const person& that)
    name =;
    age = that.age;
    return *this;

// 3. destructor

Memberwise copying is exactly what we want in this case:
name and age are copied, so we get a self-contained, independent person object.
The implicitly-defined destructor is always empty.
This is also fine in this case since we did not acquire any resources in the constructor.
The members’ destructors are implicitly called after the person destructor is finished:

After executing the body of the destructor and destroying any automatic objects allocated within the body,
a destructor for class X calls the destructors for X’s direct […] members
[n3126.pdf 12.4 §6]

Managing resources

So when should we declare those special member functions explicitly?
When our class manages a resource, that is,
when an object of the class is responsible for that resource.
That usually means the resource is acquired in the constructor
(or passed into the constructor) and released in the destructor.

Let us go back in time to pre-standard C++.
There was no such thing as std::string, and programmers were in love with pointers.
The person class might have looked like this:

class person
    char* name;
    int age;


    // the constructor acquires a resource:
    // in this case, dynamic memory obtained via new[]
    person(const char* the_name, int the_age)
        name = new char[strlen(the_name) + 1];
        strcpy(name, the_name);
        age = the_age;

    // the destructor must release this resource via delete[]
        delete[] name;

Even today, people still write classes in this style and get into trouble:
I pushed a person into a vector and now I get crazy memory errors!
Remember that by default, copying an object means copying its members,
but copying the name member merely copies a pointer, not the character array it points to!
This has several unpleasant effects:

  1. Changes via a can be observed via b.
  2. Once b is destroyed, is a dangling pointer.
  3. If a is destroyed, deleting the dangling pointer yields undefined behavior.
  4. Since the assignment does not take into account what name pointed to before the assignment,
    sooner or later you will get memory leaks all over the place.

Explicit definitions

Since memberwise copying does not have the desired effect, we must define the copy constructor and the copy assignment operator explicitly to make deep copies of the character array:

// 1. copy constructor
person(const person& that)
    name = new char[strlen( + 1];
    age = that.age;

// 2. copy assignment operator
person& operator=(const person& that)
    if (this != &that)
        delete[] name;
        // This is a dangerous point in the flow of execution!
        // We have temporarily invalidated the class invariants,
        // and the next statement might throw an exception,
        // leaving the object in an invalid state :(
        name = new char[strlen( + 1];
        age = that.age;
    return *this;

Note the difference between initialization and assignment:
we must tear down the old state before assigning to name to prevent memory leaks.
Also, we have to protect against self-assignment of the form x = x.
Without that check, delete[] name would delete the array containing the source string,
because when you write x = x, both this->name and contain the same pointer.

Exception safety

Unfortunately, this solution will fail if new char[...] throws an exception due to memory exhaustion.
One possible solution is to introduce a local variable and reorder the statements:

// 2. copy assignment operator
person& operator=(const person& that)
    char* local_name = new char[strlen( + 1];
    // If the above statement throws,
    // the object is still in the same state as before.
    // None of the following statements will throw an exception :)
    delete[] name;
    name = local_name;
    age = that.age;
    return *this;

This also takes care of self-assignment without an explicit check.
An even more robust solution to this problem is the copy-and-swap idiom,
but I will not go into the details of exception safety here.
I only mentioned exceptions to make the following point: Writing classes that manage resources is hard.

Noncopyable resources

Some resources cannot or should not be copied, such as file handles or mutexes.
In that case, simply declare the copy constructor and copy assignment operator as private without giving a definition:


    person(const person& that);
    person& operator=(const person& that);

Alternatively, you can inherit from boost::noncopyable or declare them as deleted (in C++11 and above):

person(const person& that) = delete;
person& operator=(const person& that) = delete;

The rule of three

Sometimes you need to implement a class that manages a resource.
(Never manage multiple resources in a single class,
this will only lead to pain.)
In that case, remember the rule of three:

If you need to explicitly declare either the destructor,
copy constructor or copy assignment operator yourself,
you probably need to explicitly declare all three of them.

(Unfortunately, this “rule” is not enforced by the C++ standard or any compiler I am aware of.)

The rule of five

From C++11 on, an object has 2 extra special member functions: the move constructor and move assignment. The rule of five states to implement these functions as well.

An example with the signatures:

class person
    std::string name;
    int age;

    person(const std::string& name, int age);        // Ctor
    person(const person &) = default;                // 1/5: Copy Ctor
    person(person &&) noexcept = default;            // 4/5: Move Ctor
    person& operator=(const person &) = default;     // 2/5: Copy Assignment
    person& operator=(person &&) noexcept = default; // 5/5: Move Assignment
    ~person() noexcept = default;                    // 3/5: Dtor

The rule of zero

The rule of 3/5 is also referred to as the rule of 0/3/5. The zero part of the rule states that you are allowed to not write any of the special member functions when creating your class.


Most of the time, you do not need to manage a resource yourself,
because an existing class such as std::string already does it for you.
Just compare the simple code using a std::string member
to the convoluted and error-prone alternative using a char* and you should be convinced.
As long as you stay away from raw pointer members, the rule of three is unlikely to concern your own code.


  • 4

    Fred, I’d feel better about my up-vote if (A) you wouldn’t spell out badly implemented assignment in copyable code and add a note saying it’s wrong and look elsewhere in the fineprint; either use c&s in the code or just skip over implementing all these members (B) you would shorten the first half, which has little to do with the RoT; (C) you would discuss the introduction of move semantics and what that means for the RoT.

    – sbi

    Nov 13, 2010 at 14:00

  • 7

    But then the post should be made C/W, I think. I like that you keep the terms mostly accurate (i.e that you say “copy assignment operator”, and that you don’t tap into the common trap that assignment couldn’t imply a copy).

    Nov 13, 2010 at 14:21

  • 5

    @Prasoon: I don’t think cutting out half of the answer would be seen as “fair editing” of a non-CW answer.

    – sbi

    Nov 13, 2010 at 14:33

  • 75

    It would be great if you update your post for C++11 (i.e. move constructor / assignment)

    Sep 13, 2012 at 3:42

  • 7

    @solalito Anything you must release after use: concurrency locks, file handles, database connections, network sockets, heap memory…

    Nov 18, 2015 at 10:13


The Rule of Three is a rule of thumb for C++, basically saying

If your class needs any of

  • a copy constructor,
  • an assignment operator,
  • or a destructor,

defined explictly, then it is likely to need all three of them.

The reasons for this is that all three of them are usually used to manage a resource, and if your class manages a resource, it usually needs to manage copying as well as freeing.

If there is no good semantic for copying the resource your class manages, then consider to forbid copying by declaring (not defining) the copy constructor and assignment operator as private.

(Note that the forthcoming new version of the C++ standard (which is C++11) adds move semantics to C++, which will likely change the Rule of Three. However, I know too little about this to write a C++11 section about the Rule of Three.)


  • 3

    Another solution to prevent copying is to inherit (privately) from a class that cannot be copied (like boost::noncopyable). It can also be much clearer. I think that C++0x and the possibility to “delete” functions could help here, but forgot the syntax :/

    Nov 13, 2010 at 16:33

  • 2

    @Matthieu: Yep, that works, too. But unless noncopyable is part of the std lib, I don’t consider it much of an improvement. (Oh, and if you forgot the deletion syntax, you forgot mor ethan I ever knew. :))

    – sbi

    Nov 13, 2010 at 17:20

  • 4

    @Daan: See this answer. However, I’d recommend to stick to Martinho‘s Rule of Zero. To me, this is one of the most important rules of thumb for C++ coined in the last decade.

    – sbi

    Jun 4, 2014 at 17:46

  • 4

    Martinho’s Rule of Zero now better (without apparent adware takeover) located on

    Jun 27, 2018 at 18:31


The law of the big three is as specified above.

An easy example, in plain English, of the kind of problem it solves:

Non default destructor

You allocated memory in your constructor and so you need to write a destructor to delete it. Otherwise you will cause a memory leak.

You might think that this is job done.

The problem will be, if a copy is made of your object, then the copy will point to the same memory as the original object.

Once, one of these deletes the memory in its destructor, the other will have a pointer to invalid memory (this is called a dangling pointer) when it tries to use it things are going to get hairy.

Therefore, you write a copy constructor so that it allocates new objects their own pieces of memory to destroy.

Assignment operator and copy constructor

You allocated memory in your constructor to a member pointer of your class. When you copy an object of this class the default assignment operator and copy constructor will copy the value of this member pointer to the new object.

This means that the new object and the old object will be pointing at the same piece of memory so when you change it in one object it will be changed for the other objerct too. If one object deletes this memory the other will carry on trying to use it – eek.

To resolve this you write your own version of the copy constructor and assignment operator. Your versions allocate separate memory to the new objects and copy across the values that the first pointer is pointing to rather than its address.


  • 4

    So If we use a copy constructor then the copy is made but at a different memory location altogether and if we do not use copy constructor then copy is made but it points to the same memory location. is that what you are trying to say? So a copy without copy constructor means that a new pointer will be there but pointing to the same memory location however if we have copy constructor explicitly defined by user then we will have a separate pointer pointing to a different memory location but having the data.

    Jan 4, 2015 at 14:01

  • 4

    Sorry, I replied to this ages ago but my reply does not seem to still be here 🙁 Basically, yes – you get it 🙂

    – Stefan

    Jul 27, 2016 at 13:35