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;
}
source to share
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
source to share
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).
source to share