
On 5/3/2010 3:52 PM, Chad Nelson wrote:
On 05/03/2010 06:37 PM, Jeffrey Lee Hellrung, Jr. wrote:
[...] I just realized that, since I have the boost::move calls wrapped in a #define already, it would be easy to check on that, so I did. The timings all indicate that without the boost::move() call for the return values, XInt runs as if Boost.Move weren't even there. So the boost::move call *is* required to get the benefits of emulated move semantics, as I originally thought.
Sorry, I *definitely* should've added that, as far as I know, RVO generally requires a single, simple return statement. If you have multiple returns, or a return expression more complicated than "return foo;" or "return T(bar,zap);", then I don't think RVO typically kicks in. Can you confirm or deny this to be the case? If it is, then the move(...) calls or COW will almost certainly be necessary to get optimal performance.
In the cases I'm looking at, there are usually only three lines in the function: a declaration of an integer to hold the return value, a call to a function in the detail namespace to do the operation (with the return value object as a parameter), and a return of the return value. - From what you're saying, RVO should be easy for the compiler to use, but the boost::move call on that return value is still required to get the benefits of move semantics.
(That three-line function design is what is preventing the move semantics from working as well as they could, I'm pretty sure. I haven't had enough time to confirm that yet though.)
Hmmm....can you give a stripped-down example of where you expect (or, perhaps, where I claim) RVO should kick in, but doesn't? I tried the following program to test RVO, and emulated the basic function structure you describe above. -------------------------------- #include <iostream> struct X { int x; X() : x(0) { std::cout << "X::X()" << std::endl; } X(const X& other) : x(other.x) { std::cout << "X::X(const X&)" << std::endl; } }; void f(X& x) { x.x = 1; } X g() { X x; f(x); return x; } int main() { X x = g(); return 0; } -------------------------------- With MSVC9, debug build gives output "X::X()"/"X::X(const X&)", while release build gives output "X::X()" (i.e., no call to X::X(const X&)). - Jeff