3

I'm a beginner in C++ and the resource I'm using says that the following statement d3 = d1 + d2; calls the following:

  • The + operator
  • The default constructor
  • The copy constructor
  • Destructor
  • Assignment operator
  • Destructor

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

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;
}
Daniel Taylor
  • 81
  • 1
  • 10

5 Answers5

8

The expression (d1 + d2) yields a temporary object while returning from operator+ (return temp). The creation of the temporary from 'temp' is done through the copy constructor. This is then assigned to d3.

Chubsdad
  • 24,777
  • 4
  • 73
  • 129
  • 1
    Note that with NRVO/RVO, you may not see the call to the copy constructor. Please read up on Copy elision (http://stackoverflow.com/questions/2581424/how-to-check-for-c-copy-ellision) – Chubsdad Jan 24 '13 at 07:32
  • @DanielTaylor interesting, I would have expected *named value optimization* to elide the copy construction. – juanchopanza Jan 24 '13 at 07:33
  • @DanielTaylor see [here](http://ideone.com/s4omHW#view_edit_box) for an example of RVO (albeit without the N) in action. – juanchopanza Jan 24 '13 at 07:35
  • @juanchopanza: may be a case of Debug vs Release build. – Matthieu M. Jan 24 '13 at 10:24
2

When it calculates d1+d2, the result is a temporary object. For assigning one object to another the copy constructor is being called.

nabroyan
  • 3,225
  • 6
  • 37
  • 56
  • The wording is confusing. For assigning one object to another, what is really called is the assignment operator. – juanchopanza Jan 24 '13 at 07:48
  • In operator+ for `return temp;` a temporary object is being made, for that the copy constructor is being called. This happens before reaching to assigning operator. Sorry for my English. – nabroyan Jan 24 '13 at 08:20
1

By default, return'ing an object by value will copy-construct a temporary object from the source object and then pass along that temporary to the caller. In other words, the statement d3 = d1 + d2; is basically doing this:

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

Which breaks up 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

It is the same order as the output you are seeing.

If the compiler supports RVO (Return Value Optimization), it would be able to optimize away the temporary date object created by the return statement, by passing d3 has a hidden parameter so return can just assign the temp variable directly to d3 via its = operator, making the code behavior 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;
}

Which would break down to 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
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

copy constructor is called when:

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

your + operator overloading function returns a temporary object.which will actually call a copy constructor.

Vijay
  • 65,327
  • 90
  • 227
  • 319
0

Don't rely on that

Technically, your operator+ has a temp variable into its block that has to be passed outside it into a temporary object to be later given to your operator=.

In other word, what your operator= see as a parameter is not the temp inside operator+, but a copy of it, that have to live longer than the + block, to let = to take place.

Howvever, if either:

  • + has just only one return statement (as it actually have)
  • + has all the return statements returning always just a same object

The compiler can optimize the copy-on-return by merging the temp local variable with the temporary used in the assignment, and leave out the copy at all.

This is one of very few optimization that can happen also cutting away side effects (see §12.8.15 of C++03 or 12.8.31 of C++11).

The fact the copy constructor is called or not, ultimately, depends on the compiler an on the level of optimization required.

(thanks to juanchopanza for all the clarifications).

Community
  • 1
  • 1
Emilio Garavaglia
  • 20,229
  • 2
  • 46
  • 63
  • Copy elision can occur even if copy c-tor has side effects, no? Or is that allowed only in RVO? – jrok Jan 24 '13 at 08:46
  • @jrok: Being an optimization, it happens only if the external effect remains the same. If the copy ctor has side-effects, eliding will also elide the side effects, and this will change the external behavior. – Emilio Garavaglia Jan 24 '13 at 08:50
  • @jrok You are right, copy elision *is* allowed to happen even if it eliminates side effects. It is an optimization that *can* change external behaviour. That is one reason it is really essential to know about it. Concerning this point, the answer is incorrect. Concerning the single return statement point, that isn't completely correct either. It can work if all return statements return the same object. – juanchopanza Jan 24 '13 at 10:29
  • @juanchopanza: If -just for completness- you can specify the point of the standard that says it can be done even eliminating side effects I'll fix the answer. (Or better: I can delete this if you post the correct one. Right now this is the only palace that talks about copy elision in the page, so it cannot be eliminated) – Emilio Garavaglia Jan 25 '13 at 12:20
  • I think it was in §12.8 in the C++03 standard. I don't have access to a copy right now, but I can check later. – juanchopanza Jan 25 '13 at 12:31
  • I just found [this related question](http://stackoverflow.com/questions/8890528/copy-constructor-elision). – juanchopanza Jan 25 '13 at 12:34
  • Also 12.8.31 of C++11. Ok: enough info. – Emilio Garavaglia Jan 25 '13 at 12:41