On Sun, 28 Apr 2013, Andrew Ho wrote:
Yeah, I did some testing with VS2012 (/O2 optimizations) using your original set and with Marc's set. Both work, but Marc's set does result in fewer temporaries all-together. To be specific, all internal moves seem to be optimized away, only move required is moving into the result variable. I think this provides all of the benefits of your previous rvalue-ref code without the unsafe behavior.
Er, no, there are many unnecessary moves in this version that would go away if we returned a reference.
One interesting behavior I noticed while testing:
1)
MyClass operator+( const MyClass& lhs, const MyClass& rhs ) { MyClass nrv(lhs); nrv += rhs; return nrv; }
2)
MyClass operator+( const MyClass& lhs, const MyClass& rhs ) { return std::move(MyClass(lhs) += rhs); }
1) and 2) do not compile equivalently. 2) for some reason does not allow the compiler to perform return value optimizations (at least the compilers I tested with), potentially resulting in extra unnecessary temporaries.
Copy elision is extremely limited. The committee basically wrote 3 examples and said it was allowed for all 3 and nothing else. One trick to help reason about it: std::move involves a reference, and the elision is for values only (the return value of += is also a reference). -- Marc Glisse