Why does the copy constructor call the d1 = d2 + d3 operator in C ++?

I am starting in C ++ and the resource I am using says the following statement is d3 = d1 + d2; calls the following:

  • Operator +
  • Default constructor
  • Copy constructor
  • Destructor
  • Assignment operator
  • Destructor

I don't understand why the copy constructor is called when the result is assigned to a previously declared variable and why the 2 constructors are called.

The operators are as follows:

date& date::operator=(const date& other)
{
cout << "Date assignment op" << endl;
    if (this!=&other){
        day=other.day;
        month=other.month;
        year=other.year;
    }
    return *this;
}

date date::operator+(const date& other) const
{
    cout << "Date Operator + called" << endl;
    date temp;
    temp.day=day+other.day;
    temp.month=month+other.month;
    temp.year=year+other.year;
    return temp;
}

      

+3


source to share


5 answers


The expression (d1 + d2)

gives a temporary object when returned from the + ( return temp

) operator . The creation of a temporary from "temp" is done through the copy constructor. This is then assigned d3.



+8


source


When it evaluates d1 + d2, the result is a temporary object. The copy constructor is called to assign one object to another.



+2


source


By default, return

'typing an object by value will copy-construct a temporary object from the original object and then pass it to the temporary call. In other words, the statement d3 = d1 + d2;

basically does the following:

date implicit_temp(operator+(d1, d2));
d3 = implicit_temp;

      

which breaks down into the following logic under the hood:

// The + operator 
date temp; // The default constructor
temp.day = d1.day + d2.day;
temp.month = d1.month + d2.month;
temp.year = d1.year + d2.year;
// return temp;
date implicit_temp(temp); // The copy constructor
temp.~date(); // Destructor
// Assignment operator
d3.day = implicit_temp.day;
d3.month = implicit_temp.month;
d3.year = implicit_temp.year;
implicit_temp.~date(); // Destructor

      

This is the same order as the output you see.

If the compiler supports RVO (Return Value Optimization), it will be able to optimize the temporary object date

created by the operator return

by passing d3

has a hidden parameter, so it return

can just assign the variable temp

directly d3

through its operator =

, making the code behave as if it were written like this:

void date::operator+(const date& other, date& result) const
{
    date temp;
    temp.day=day+other.day;
    temp.month=month+other.month;
    temp.year=year+other.year;
    result = temp;
}

      

What would break with this logic under the hood:

// The + operator 
date temp; // The default constructor
temp.day = d1.day + d2.day;
temp.month = d1.month + d2.month;
temp.year = d1.year + d2.year;
// return temp; - Assignment operator
d3.day = temp.day;
d3.month = temp.month;
d3.year = temp.year;
temp.~date(); // Destructor

      

+1


source


Copy constructor

called when:

A a=b,
when you return an object,
when you pass an object.

      

your operator overloading function +

returns a temporary object that will actually call the copy constructor.

0


source


Don't rely on it

Technically, yours operator+

has a variable temp

in its block that needs to be passed outside of it into a temporary object that will then be passed to yours operator=

.

In other words, what your operator=

sees as a parameter is not temp

inside operator+

, but a copy of it, which must live longer than the block +

to =

take place.

How to get it if:

  • +

    has only one return statement (as it actually is)
  • +

    has all return statements that always return the same object

The compiler can optimize copy-on-return by merging the local temp variable with the temporary assignment in the assignment and leaving it out of the copy altogether.

This is one of the very few optimizations that can occur to eliminate side effects as well (see ยง 12.8.15 from C ++ 03 or 12.8.31 from C ++ 11).

Whether the copy constructor is called or not is ultimately up to the compiler at the required level of optimization.

(thanks to juanchopanza for all the clarifications).

0


source







All Articles