What you experience is called return value optimization (see What are copy elision and return value optimization?).
The compiler optimizes code (to minimize objects created) and makes a
actually be the local object declared and returned by your+
operator. Then, there is no copy constructor used. This is what you observe here.
To nicely observe this, change your code to see object memory adresses:
#include <iostream>
using namespace std;
class MyClass
{
public:
MyClass()
{
cout << "default constructor has been called for " << std::hex << this << endl;
}
MyClass(const MyClass& cls)
{
cout << "copy constructor has been called for " << std::hex << this << " (copied from " << &cls << ")" << endl;
}
MyClass operator+(const MyClass& cls) const
{
cout << "operator + has been called!" << endl;
MyClass res;
cout << "operator + returns temporary object " << std::hex << &res << endl;
return res;
}
MyClass& operator=(const MyClass& cls)
{
cout << "operator = has been called!" << endl;
return *this;
}
};
int main()
{
MyClass b, c;
MyClass a = b + c;
cout << "a object is " << std::hex << &a << endl;
return 0;
}
It outputs:
default constructor has been called for 0x7ffd44b769fd
default constructor has been called for 0x7ffd44b769fe
operator + has been called!
default constructor has been called for 0x7ffd44b769ff
operator + returns temporary object 0x7ffd44b769ff
a object is 0x7ffd44b769ff
You see that temporary object created in operator+
is the same as a
(0x7ffd44b769ff
), due to compiler optimization.
If you use g++, compile with -fno-elide-constructors
to disable this compiler optimization. And the output is now:
default constructor has been called for 0x7ffd92847d1c
default constructor has been called for 0x7ffd92847d1d
operator + has been called!
default constructor has been called for 0x7ffd92847cff
operator + returns temporary object 0x7ffd92847cff
copy constructor has been called for 0x7ffd92847d1f (copied from 0x7ffd92847cff)
copy constructor has been called for 0x7ffd92847d1e (copied from 0x7ffd92847d1f)
a object is 0x7ffd92847d1e
You see that now operator+
creates a local object (0x7ffd92847cff
), which is later copied as a temporary object for return statement (copying 0x7ffd92847cff
to 0x7ffd92847d1f
), which is finally used to construct a by copy (copying 0x7ffd92847d1f
to 0x7ffd92847d1e
).