In which situations is the C++ copy constructor called?

Pandrei picture Pandrei · Jan 18, 2014 · Viewed 29.9k times · Source

I know of the following situations in c++ where the copy constructor would be invoked:

  1. when an existing object is assigned an object of it own class

    MyClass A,B;
    A = new MyClass();
    B=A; //copy constructor called 
    
  2. if a functions receives as argument, passed by value, an object of a class

    void foo(MyClass a);
    foo(a); //copy constructor invoked
    
  3. when a function returns (by value) an object of the class

    MyClass foo ()
       {
          MyClass temp;
          ....
          return temp; //copy constructor called
       } 
    

Please feel free to correct any mistakes I've made; but I am more curious if there are any other situations in which the copy constructor is called.

Answer

0x499602D2 picture 0x499602D2 · Jan 18, 2014

When an existing object is assigned an object of it own class

    B = A;

Not necessarily. This kind of assignment is called copy-assignment, meaning the assignment operator of the class will be called to perform memberwise assignment of all the data members. The actual function is MyClass& operator=(MyClass const&)

The copy-constructor is not invoked here. This is because the assignment operator takes a reference to its object, and therefore no copy-construction is performed.

Copy-assignment is different from copy-initialization because copy-initialization is only done when an object is being initialized. For example:

T y = x;
  x = y;

The first expression initializes y by copying x. It invokes the copy-constructor MyClass(MyClass const&).

And as mentioned, x = y is a call to the assignment operator.

(There is also something called copy-elison whereby the compiler will elide calls to the copy-constructor. Your compiler more than likely uses this).


If a functions receives as argument, passed by value, an object of a class

    void foo(MyClass a);
    foo(a);

This is correct. However, note that in C++11 if a is an xvalue and if MyClass has the appropriate constructor MyClass(MyClass&&), a can be moved into the parameter.

(The copy-constructor and the move-constructor are two of the default compiler-generated member functions of a class. If you do not supply them yourself, the compiler will generously do so for you under specific circumstances).


When a function returns (by value) an object of the class

    MyClass foo ()
    {
        MyClass temp;
        ....
        return temp; // copy constructor called
    }

Through return-value optimization, as mentioned in some of the answers, the compiler can remove the call to the copy-constructor. By using the compiler option -fno-elide-constructors, you can disable copy-elison and see that the copy-constructor would indeed be called in these situations.