Home > Enterprise >  How (or why) the copy constructor is called?
How (or why) the copy constructor is called?

Time:02-03

#include <iostream>

using namespace std;

struct Car
{
    int size = 4;
    int* tires = nullptr;

    Car()
    {
        cout << "ctor" << endl;
        tires = new int[size];
    }

    Car(const Car& car)
    {
        cout << "copy ctor" << endl;
        tires = new int[size];
        memcpy(tires, car.tires, size*sizeof(int));
    }

    Car& operator= (Car& car)
    {
        cout << "copy assignment operator" << endl;
        tires = new int[size];
        memcpy(tires, car.tires, size*sizeof(int));
        return *this;
    }

     ~Car()
    {
        cout << "dtor" << endl;
        delete tires;
    }
};

int main()
{
    cout  << "starting..." << endl;

    Car car1;
    car1.tires[0] = 2;

//    Car car2(car1); // #1
    Car car2 = car1; // #2 I was expecting the assingment operator to be called here

    cout << car1.tires[0] << " " << car2.tires[0] << endl;

    return 0;
}

I understand why the copy constructor is called at #1, but how does it end up being called at #2?

CodePudding user response:

The statement:

Car car2 = car1;

is NOT assignment, like you are thinking. Assignment can happen only on an existing object, not when an object is being created.

The statement above is actually initialization instead, specifically Copy Initialization:

Syntax

T object = other; (1)

...

The effects of copy initialization are:

  • ...

  • Otherwise, if T is a class type and the cv-unqualified version of the type of other is T or a class derived from T, the non-explicit constructors of T are examined and the best match is selected by overload resolution. That constructor is then called to initialize the object.

  • ...

So, in your case, the compiler finds the copy constructor is a match and treats the statement as-if you had written Car car2(car1); instead.

That is why the copy constructor is called.

CodePudding user response:

A C compiler will call the assignment operator only for an object that already exists, to overwrite the values of this object with the values of another instance.

car car1,car2;
car2=car1;

And it will call the copy constructor in the below cases:

  1. if the object is initialized with another instance.

      car car1;
      car car2=car1; //This is equivalent to car2(car1);
    
  2. if an object is passed to a function as a non-reference parameter.

    Here you can see the parameter of func, where the obj2 is being initialized and not assigned.

     void func(car obj2)//not a reference parameter(car& obj2)
     {
      //
     }
    
     car obj1;
     func(obj1);
    
  3. An object is returned from a function - I don't have an idea about this yet.

Initialization is when a new object or variable is being created to hold a value, and assignment is when an existing object or variable is set to hold a new value.

For the above assignment operator example, both the car1 and car2 objects hold a value (probably garbage) at the time of creation, and then are set to a new value.

I hope this helps.

  • Related