C++ allows to avoid creating and copying extra objects in cases like yours. This is known as the named return value optimization. The point is that you know for sure that after the return the object temp
would be gone anyway, and the semantics of the copy constructor should be to make an exactly equivalent copy to the original object.
Note that actually there are two optimizations occuring here. Without optimization, the object temp
would first be copied into the return value in g
, and then the return value would be copied to h2
in main
. The named return value optimization elides the copy into the return value. Copying from the return value into h2
is elided because the return value is a temporary object, and here, too, the creation of a copy may be elided.
Note that unlike other optimizations, these optimizations are allowed even if they change observable behaviour (as in your test program). That's because otherwise these optimization could not be performed in many cases where it doesn't make a difference (indeed, except for debugging output, this should never make a difference in a well-written program), because the compiler often cannot proof that the elision would not change observable behaviour. On the other hand, there's no way to manually remove the copies,so it is important for the compiler to be able to do it automatically.
What ultimately happens is that the object temp
is directly created in the space h2
occupies, so that at the point of the return statement h2
does already contain the correct value. In other words, due to the optimizations temp
and h2
are actually the same object.