You can verify this yourself, because the optimization in question has observed differences!
Most forms of optimization in C ++ follow the as-if
rule, which makes them difficult to detect. However, in some cases it is allowed to return (copy) the copy and move the constructor, even if the difference leads to observable changes in behavior.
In this case, add the following to S:
struct S { // ... S( S const& o ):x(ox), y(oy), z(oz) { std::cout << "copy ctor!\n"; } S& operator=( S const& o ) { x=ox; y=oy; z=oz; std::cout << "copy assign!\n"; return *this; } S( S && o ):x(std::move(ox)), y(std::move(oy)), z(std::move(oz)) { std::cout << "move ctor!\n"; } S& operator=( S const& o ) { std::tie( x,y,z ) = std::tie( std::move(ox),std::move(oy),std::move(oz) ); std::cout << "move assign!\n"; return *this; } }
and run your code. With zero optimization, you will get copies and / or relocation.
At any non-trivial level of optimization, the fingerprints will disappear because the RVO (and, as appropriate, NRVO) will work, excluding the copies. (If your compiler is not C ++ 11, remove the move constructors above - optimization in C ++ 03 is still allowed)
In C ++ 11, you can explicitly build the return value instead of relying on NRVO / RVO using the return {stuff}
syntax.
Note that RVO (return value optimization) and NRVO (called return value optimization) are relatively fragile, and if you rely on them, you both need to understand how they work, which makes them break, and any quirks of your particular compiler have in its implementation (if any).