Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 355
Pandrei Avatar asked Jan 18 '14 15:01

Pandrei


People also ask

In which situation constructor is called in C++?

A constructor in C++ is a special method that is automatically called when an object of a class is created.

What is copy constructor in C language?

The copy constructor is a type of constructor. It creates an object and initializes it with an object of the same class. If the copy constructor is not defined in the class, the compiler itself defines one. A copy constructor is a must for a class that has pointer variables or dynamic memory allocations.

When a copy constructor is not get called?

The reason the copy constructor is not called is because the copy constructor itself is a function with one parameter.

Why is copy constructor called reference?

A copy constructor defines what copying means,So if we pass an object only (we will be passing the copy of that object) but to create the copy we will need a copy constructor, Hence it leads to infinite recursion. So, A copy constructor must have a reference as an argument.


3 Answers

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.

like image 50
David G Avatar answered Oct 18 '22 06:10

David G


I might be wrong about this, but this class allows you to see what is called and when:

class a {
public:
    a() {
        printf("constructor called\n");
    };  
    a(const a& other) { 
        printf("copy constructor called\n");
    };    
    a& operator=(const a& other) {
        printf("copy assignment operator called\n");
        return *this; 
    };
};

So then this code:

a b; //constructor
a c; //constructor
b = c; //copy assignment
c = a(b); //copy constructor, then copy assignment

produces this as the result:

constructor called
constructor called
copy assignment operator called
copy constructor called
copy assignment operator called

Another interesting thing, say you have the following code:

a* b = new a(); //constructor called
a* c; //nothing is called
c = b; //still nothing is called
c = new a(*b); //copy constructor is called

This occurs because when you when you assign a pointer, that does nothing to the actual object.

like image 23
BWG Avatar answered Oct 18 '22 05:10

BWG


Situation (1) is incorrect and does not compile the way you've written it. It should be:

MyClass A, B;
A = MyClass(); /* Redefinition of `A`; perfectly legal though superfluous: I've
                  dropped the `new` to defeat compiler error.*/
B = A; // Assignment operator called (`B` is already constructed)
MyClass C = B; // Copy constructor called.

You are correct in case (2).

But in case (3), the copy constructor may not be called: if the compiler can detect no side effects then it can implement return value optimisation to optimise out the unnecessary deep copy. C++11 formalises this with rvalue references.

like image 12
Bathsheba Avatar answered Oct 18 '22 06:10

Bathsheba