6

I simply created a class like this:

class GreatClass
{
public:
    GreatClass(){cout<<"Default Constructor Called!\n";}
    GreatClass(GreatClass &gc){cout<<"Copy Constructor Called!\n";}
    GreatClass(const GreatClass &gc){cout<<"Copy Constructor (CONST) Called!\n";}
    ~GreatClass(){cout<<"Destructor Called.\n";}
    GreatClass& operator=(GreatClass& gc){cout<<"Assign Operator Called!";return gc;}
    const GreatClass& operator=(const GreatClass& gc){cout<<"Assign Operator (CONST) Called!";return gc;}
};

GreatClass f(GreatClass gc)
{
    return gc;
}

and in main() function, there are two versions:

version #1:

int main()
{
    GreatClass g1;
    GreatClass G = f(g1);
}

version #2:

int main()
{
    GreatClass g1;
    f(g1);
}

They all generates the SAME output:

Default Constructor Called!
Copy Constructor Called!
Copy Constructor Called!
Destructor Called.
Destructor Called.
Destructor Called.

I do not understand why there is nothing happening when I'm assigning f(g1) to G. What constructor or operator is called at this point?

Thanks.

Renfei Song
  • 2,941
  • 2
  • 25
  • 30
  • 4
    Copy elision is what is going on. If you are using GCC, try the `-fno-elide-constructors` compilation flag. – Andy Prowl Jul 01 '13 at 16:56
  • I think maybe part of your confusion is why `operator=` is not used. This is dictated by the standard. Things of the form `A a2 = a1;` are copy-initialization, and the copy constructor is used (not the assignment operator). Copy elision can come into play as well. – huskerchad Jul 01 '13 at 18:49

1 Answers1

13

Compiler implementations are allowed to elide/remove copy constructor calls in certain cases, the example you specify is a good example use case of such a scenario. Instead of creating a temporary object and then copying it to destination object the object is created directly in the destination object and the copy constructor call is removed out.

This optimization is known as Copy elision through Return value optimization.

Also, with C++11 move semantics through rvalue references might kick in instead of the Copy semantics. Even with move semantics the compilers are still free to apply RVO.

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533