9.11 — The copy constructor

Recapping the types of initialization

Since we’re going to talk a lot about initialization in the next few lessons, let’s first recap the types of initialization that C++ supports: direct initialization, uniform initialization or copy initialization.

Here’s examples of all of those, using our Fraction class:

We can do a direct initialization:

In C++11, we can do a uniform initialization:

And finally, we can do a copy initialization:

With direct and uniform initialization, the object being created is directly initialized. However, copy initialization is a little more complicated. We’ll explore copy initialization in more detail in the next lesson. But in order to do that effectively, we need to take a short detour.

The copy constructor

Now consider the following program:

If you compile this program, you’ll see that it compiles just fine, and produces the result:

Let’s take a closer look at how this program works.

The initialization of variable fiveThirds is just a standard direct initialization that calls the Fraction(int, int) constructor. No surprises there. But what about the next line? The initialization of variable fCopy is also clearly a direct initialization, and you know that constructor functions are used to initialize classes. So what constructor is this line calling?

The answer is that this line is calling Fraction’s copy constructor. A copy constructor is a special type of constructor used to create a new object as a copy of an existing object. And much like a default constructor, if you do not provide a copy constructor for your classes, C++ will create a public copy constructor for you. Because the compiler does not know much about your class, by default, the created copy constructor utilizes a method of initialization called memberwise initialization. Memberwise initialization simply means that each member of the copy is initialized directly from the member of the class being copied. In the above example, fCopy.m_numerator would be initialized from fiveThirds.m_numerator, etc…

Just like we can explicitly define a default constructor, we can also explicitly define a copy constructor. The copy constructor looks just like you’d expect it to:

When this program is run, you get:

Copy constructor called

The copy constructor we defined in the example above uses memberwise initialization, and is functionally equivalent to the one we’d get by default, except we’ve added an output statement to prove the copy constructor is being called.

Unlike with default constructors (where you should always provide your own default constructor), it’s fine to use the default copy constructor if it meets your needs.

One interesting note: You’ve already seen a few examples of overloaded operator<<, where we’re able to access the private members of parameter f1 because the function is a friend of the Fraction class. Similarly, member functions of a class can access the private members of parameters of the same class type. Since our Fraction copy constructor takes a parameter of the class type (to make a copy of), we’re able to access the members of parameter fraction directly, even though it’s not the implicit object.

Preventing copies

We can prevent copies of our classes from being made by making the copy constructor private:

Now when we try to compile our program, we’ll get a compile error since fCopy needs to use the copy constructor, but can not see it since the copy constructor has been declared as private.

The copy constructor may be elided

Now consider the following example:

Consider how this program works. First, we direct initialize an anonymous Fraction object, using the Fraction(int, int) constructor. Then we use that anonymous Fraction object as an initializer for Fraction fiveThirds. Since the anonymous object is a Fraction, as is fiveThirds, this should call the copy constructor, right?

Run this and compile it for yourself. You’d probably expect to get this result (and you may):

copy constructor called

But in actuality, you’re more likely to get this result:


Why didn’t our copy constructor get called?

Note that initializing an anonymous object and then using that object to direct initialize our defined object takes two steps (one to create the anonymous object, one to call the copy constructor). However, the end result is essentially identical to just doing a direct initialization, which only takes one step.

For this reason, in such cases, the compiler is allowed to opt out of calling the copy constructor and just do a direct initialization instead. This process is called elision.

So although you wrote:

The compiler may change this to:

which only requires one constructor call (to Fraction(int, int)). Note that in cases where elision is used, any statements in the body of the copy constructor are not executed, even if they would have produced side effects (like printing to the screen)!

Prior to C++17, copy elision is an optimization the compiler can make. As of C++17, some cases of copy elision (including the example above) have been made mandatory.

Finally, note that if you make the copy constructor private, any initialization that would use the copy constructor will cause a compile error, even if the copy constructor is elided!

9.12 -- Copy initialization
9.10 -- Overloading typecasts

65 comments to 9.11 — The copy constructor

  • salah

    Hi, what is the benefit of making copy constructor private?

  • Tompouce

    At the very end of this saction you said that trying to initialise an object in a way that would call the copy constructor would fail if the constructor was made private.
    But I have notied that it doesn't seem to apply when giving an annonymous object to the private copy constructor.
    Here's what I mean:

    This seems like an inconsistency, is there an explanation for this? Or maybe I'm missing some detail.

    Edit: Here I'm using direct initialisation to define otherFooCopy, but using copy or uniform initialisation exhibits the same behaviour.

    • nascardriver

      That's a forward declaration of a function, not a variable.

      You can create a variable with brace initialization

      This works, even if the copy constructor is private, because it doesn't use the copy constructor. If you're initializing an object of type `Foo` with a temporary `Foo`, the copy has to be elided (since C++17). Before C++17, you'd get an error, because the copy constructor is private.

      • Tompouce

        Wow, I would have never guesed that this was a function forward declaration x)
        (unless I had looked more closely at what my IDE was saying :p...)

        So it's a forward declaration for a function that returns a Foo and takes... a function with no parameters, and returning Foo? Did I get this right?

  • Puya

    Hi Alex,
    As always thank you for the great tutorials.
    1- Would there ever be a point in defining the body of the copy constructor if it is private? Since if it is ever used the compiler will give an error. (except having one public copy constructor call a private one)
    2- Is declaring a constructor as private the same as deleting it?
    3- You might want to change `...since copy must already be a valid Fraction...` to `...since fraction must already be a valid Fraction...`.

    • Alex

      1) A private copy constructor could still be used by any function that has access to private member functions, which includes member functions and friend functions.
      2) No, for the same reason as #1. A deleted copy constructor can't be used by anybody.
      3) Thanks, fixed!

  • Big Chungus

    Look what I did with two class types!

  • btnal

    When a class has properties that are pointers, what is the problem of using the default copy constructor? How do you handle the problem?

  • Ran

    I found a more creepy things after I read Alex code:

    This is my original definition of the operatro+=

    If I do the solution(using the default constructor) given by Alex, it
    won't compile.

    My code, actually treat the number on the left hand side of that
    equation as the first private member m_sum using the initialization
    list. But you can see that, to make the program running, I did an
    awful thing:

    But I still do not know why "this" pointers still works in the
    following code?

    Averaged& Averaged::operator+=(const Averaged &avg)
        this->m_sum += avg.m_sum;
        this->m_number += (avg.m_number+1); // how to improve this +1??

        return *this;

    How two "this" work good?

    • nascardriver

      Hi Ran!

      > This is my original definition of the operator+=
      When you only have the operator

      and write

      the constructor of @Averaged will be called, 8 is converted to an @Averages, then the operator+= is called. This is not what you want. You should write an operator+= that takes an int.

      > But I still do not know why "this" pointers still works in the
      following code?
      I can't think of an example where this is actually useful. All it does is allow you to use the object right after using the operator:

  • Aitor

    Hi Alex,
    I have encounter one issue that i don't understand with the following code. It could be great if you can find some time to clarify my doubt. Having the code below:

    The output of these is the following:

    constructor: 0
    CopyConstructor: 1
    constructor: 2
    Desctructor: 1
    Desctructor: 2
    Desctructor: 0

    Because the return type is by value and the localFoo its gonna go out of scope it should be call copy constructor again to my understanding, making a new object with id 3, or even a 4th object.
    My questions are the folowing:
    - Shouldn't be,object two, call to the constructor after the object localFoo had return?
    - Shoudn't be, the copy constructor be called again to make a copy of localFoo when localFoo is     returned to main?
    - Is it the copy constructor being also elided in this situation?

    Im just confusing myself a bit...hehe

    Thanks for your time, and sorry for the inconvenience,Aitor

    • Alex

      Yes, the copy constructor would normally be called once when one is copied into parameter c1, and once when localFoo is used to initialize two. However, given the actual output, it looks like the return value of funcion is getting elided (as a compiler optimization). Try compiling using a debug build target and see if you see the copy constructor get called twice.

    • Pointer

      For me this programm does not compile. It compiled when definition of the static variable was added in the global namespace:

  • Copy constructors are widely used for creating a duplicates of objects known as cloned objects. Duplicate object in the sense the object will have the same characteristics of the original object from which duplicate object is created.

  • Akshay

    Why is copy constructor's argument a 'const'? I read on other sites stating that compiler creates temporary object and to hold them non-const ref would not be a good idea, I could not get it clearly, please can you explain the exact reason in details.

    • Alex

      A non-const reference can only bind to l-values. A const reference can bind to l-values or r-values, which makes it much more flexible. There are cases where we want to copy r-values, and we don't need to modify the argument anyway, so it makes sense to use the const reference.

  • hit4man47

    Hey alex,

    Why copy constructor is not called??

    • Alex

      Because when o2=o1 is executed, o2 isn't being constructed -- it's being assigned. It was already constructed on the previous line.

      If you want to call the copy constructor, create o2 like this: "dummy o2(o1)".

  • deeksha

    Hi Alex, my question is, Why pass by value is not allowed in copy constructor.
    Note:I have read the answers on internet. They say pass by value is pass by copy, means this would call the copy constructor,and it goes in a loop.
    But I can't visualise the loop. Could you please make it simpler for me using an example?


    Thank you. You are awesome.

    • Alex

      First, let's agree that the copy constructor is used to copy one object into another object of the class type. Second, let's agree that the copy constructor is used when passing a class object by value.

      Now consider what happens when you instantiate "complex1 c2(c1)". Since c1 is passed by value in this example, argument c1 needs to be copied into constructor parameter c. Per the above, this will result in a call to the copy constructor. If the copy constructor argument was passed by reference, no problem. c would be a reference to c1, and this would be used to initialize object c2.

      But instead, you've defined your copy constructor to have the argument passed by value. How do we pass an argument by value? By using the copy constructor! So your copy constructor call would call itself to try and resolve copying the argument into the parameter. This in turn, would call the copy constructor again to resolve the copying of THAT argument into the parameter.

      In other words, each call to the copy constructor results in another call to the copy constructor to copy the argument into the parameter. This sets up an infinite series of recursive copy constructor function calls. Consequently, the compiler disallows this.

  • Rakesh


    As i was unable to get a convincing answer, posting it here.

    Please tell me the consequences(good/bad) of using a pointer in a copy constructor. Why is a reference used most of the times.


    • Alex

      By "using a pointer in a copy constructor", I presume you mean having the copy constructor take a pointer parameter instead of a reference? The short answer is that the C++ specification requires copy constructors to take a reference so it can "copy" objects without having to pass them by address. This makes sense when you consider that references are semantically meant to be aliases for objects -- it makes more sense to pass the actual object to be copied than a pointer to it.

      You can certainly create your own constructors that take an object by address, but it wouldn't be a copy constructor.

  • Sam

    Formatting bug: ctrl+f "Preventing copies"

  • Rakesh


    How can i access the private member of a class without using friend functions or access functions.
    Could you please let me know the possible ways to do this.

  • Soterite

    Hi Alex!

    Maybe it's just me and I simply cannot grasp something, but shouldn't the copy constructor in your second example look rather like this?:

    It seems to me, that the argument of a copy constructor is an original object. The copy constructor is special, because it is called automatically by a compiler in some situations, but in other aspects it behaves like an ordinary one. In fact this code works:

    Please rectify, if I'm wrong with something.

    Last but not least thank you VERY much for your work. Outstanding job!

    • Alex

      If you don't provide a copy constructor, the compiler will provide one for you. That's why the second example compiles without one.

      Your copy constructor above is essentially the same as mine, except mine initializes the class data and yours assigns it. Your won't work with const members.

      Did I miss the point of your question?

      • Soterite

        I'm sorry, I'm not a native speaker and maybe I didn't express myself clearly enough. It's all about naming of the argument to the copy constructor. You named it a "copy" and I simply don't understand why:

        I believe it should be called "original".

        As I understand it, the copy constructor is given an original object (via const reference) and "produces" (even if it doesn't return) a copy of that object. So it operates just like any other constructor, in particular it can be called explicitly with const reference.

        I find it confusing, that you name this argument a "copy", but maybe it is I, who misses some quirks of this constructor :)

        Kind regards

        • Alex

          Ah, I named it copy because it's the object being passed in to make a copy of. But I can see where your confusion is, since it isn't the actual copy, the implicit class is. I'll change the name.

  • Matt

    In the third full code example, which implements a copy constructor in the class definition, you left in a comment(in main) which I think should be updated to reflect the change. You wrote:
    "Fraction fCopy(fiveThirds); // Direct initialize -- with what constructor?"

  • Anddo


    should be

  • Darren

    You can pay good money to have your dangling pointer dereferenced.

  • ganesh

    How to implement in parameterized and copy constructor????

  • ritz301

    Excellent tutorial! (y)

  • jonas

    may result in memory leak?

  • jonas

    hi Alex, may you explain the dangerousness of self assignment in more details.(....In these cases, the assignment operator doesn’t need to do anything (and if the class uses dynamic memory, it can be dangerous if it does))

  • Mohammed

    Dear Alex would you check this code and plz tell me the answer of the following question;
    When i use the overrided assignment operator iam returning by value, so i think what should happen when the instruction pointer reaches return engdist(feet,inches)
    1-  2 argument constructor is called to create a temp object;
    2-  Copy constructor is called to create a copy which will be returned;

    However what actually happens is that the 2 argument is called but the copy constructor is not called, does this mean that the temp object is the one which returned to e3

    • Mohammed

      Guys if some one knows the answer please say it cuz it is driving me crazy
      and i have an interview after 1 week and one of the topics is OOP in C++

    • Alex

      I presume you're talking about what happens when we execute "e4=e3". In this case, your overloaded assignment operator is called. Because the assignment operator is returning by value, I would expect the copy constructor to be called at that point. However, compilers are allowed to optimize away copy constructors (even if they have other side effects!), and I think that what may be happening here.

  • Ankit

    Hi Alex,

    I am working on project and I got a half written code from my previous mate. He has declared copy constructors as private. Is there any specific use or advantage of using copy constructor as private? I am not able to get why someone will declare a copy contructor as private??

    Ankit Dimri

    • Alex

      Making the copy constructor private ensures that a copy can't be made of the object. This can be desirable in some cases, such as when you want to ensure only one of an object exists (e.g. a log file).

  • Siva

    why copy constructor returns this pointer while overloaded assignment operator returns. Even though both updates in this pointer. Anyone please explain this.

    Thanks in Advance,

    • Alex

      The copy constructor doesn't return anything (because it doesn't need to).

      The assignment operator returns *this so you can chain multiple assignments together (a = b = c = d)

  • Marko

    Hi Alex,

    I want to thank you for this brilliant tutorial.
    It is helping me a lot, I have c/java background and this is all what I needed.
    It is going into my head like it already was there, don't really have a sense that I am learning something new, I am reading this easier than a note I would have to write to myself.  
    Unfortunatly I dont have a money, cause I am still studying :(, but if I get a job, I will deffinitly remembre to this, and pay my debt to society (you :)).

    ty::ItIsProbablyObviouslyThatIAmNotNativeEnglishWriter(LOVE YOU)

  • rohitnitp

    how it come while defining copy constructor you used object of the same class to access private data member which belongs to that object only..since now this object as it is already created how can we access private data directly to anywhere else even if it copy constructor of the same will violate the idea of data encapsulation and data hiding..i tried to access m_nCents via GetLength() at that point but compiler has given me error..why is it so,please explain..

  • saurabh

    Here is answer to why dont we use pass by pointer in copy constructor so see following scenario

    See above example , if we take pointer type object in copy constructor
    two flaws are here
    1) We can assign NULL value to simple object of that class
    2) see this line ABC d2 = d1;
    here d2 is ABC type while d1 is ABC* type means as per rule we are violating basic rules by allowing to assign simple type with pointer type.
    If there is any pointer type member variable in side ABC class means DEEP Copy scenario like int * m_iVal; then it will crash out during calling copy constructor by passing NULL object, so stop such mistake at design time we do use const reference object of same class type in copy constructor as a parameter.Hoping this will clear you.

  • subbaiahtp

    Please let me know the B's copy constructor implementation?

    • subrat

  • Sanjeev

    For the class A can I have copy constructor like A(const A*) instead of A(const A&). What will be the difference. Can anybody please explain?

    • HYA

      Hi Sanjeev
      In that case you have to write any object intialization like this A a, aa1 = &a; ... which is a bit confusing ...but you can implement both copy contructors as

    • HYA

Leave a Comment

Put all code inside code tags: [code]your code here[/code]