IssueRaiser

> accepting a parameter by value and returning it also enables copy elision No it doesn't.

> accepting a parameter by value and returning it also enables copy elision No it doesn't. Parameters are constructed by the caller (in order to allow eliding the parameter copy, if the argument is a temporary anyway), therefore returning a parameter cannot be elided because that would have required the caller to know to construct the parameter in the return value slot. If you actually test your code, you'll see that in the `f(X x)` case, the return is not elided. With that said, in C++11, the return is automatically by move, not by copy. Any "return x;" where x is a local variable (including parameters) will be by move. But prior to C++11, it would have been a copy. This is IMO the biggest problem with relying on RVO for anything: people rarely understand all of the rules around it, and may reasonably assume that RVO will kick in in cases where it doesn't. It's even harder if you have a function with a few branches and multiple returns -- in some cases, even when the branching happens before the return variable is declared, the compiler will fail to RVO it. Luckily C++11's "returning a local variable is automatically by move" rule covers you in most such cases. FWIW, I highly recommend following Rust's rule: Only trivial, shallow types can be implicitly copied (i.e. only cases where the copy is a simple memcpy()). Anything else can only be moved, but is free to define a `clone()` method for explicit copies. If your type doesn't have a copy constructor then you can't accidentally call it. :)

Posted by kentonv on Jul 20, 2015, 8:16 PM

Tags

Related issues

Raise real-world problems, find people facing the same issue, and discuss solutions.5,500 issues0 comments

reliability (E-commerce)

> accepting a parameter by value and returning it also enables copy elision No it doesn't.

kentonvJul 20, 2015, 8:16 PM

> accepting a parameter by value and returning it also enables copy elision No it doesn't. Parameters are constructed by the caller (in order to allow eliding the parameter copy, if the argument is a temporary anyway), therefore returning a parameter cannot be elided because that would have required the caller to know to construct the parameter in the return value slot. If you actually test your code, you'll see that in the `f(X x)` case, the return is not elided. With that said, in C++11, the return is automatically by move, not by copy. Any "return x;" where x is a local variable (including parameters) will be by move. But prior to C++11, it would have been a copy. This is IMO the biggest problem with relying on RVO for anything: people rarely understand all of the rules around it, and may reasonably assume that RVO will kick in in cases where it doesn't. It's even harder if you have a function with a few branches and multiple returns -- in some cases, even when the branching happens before the return variable is declared, the compiler will fail to RVO it. Luckily C++11's "returning a local variable is automatically by move" rule covers you in most such cases. FWIW, I highly recommend following Rust's rule: Only trivial, shallow types can be implicitly copied (i.e. only cases where the copy is a simple memcpy()). Anything else can only be moved, but is free to define a `clone()` method for explicit copies. If your type doesn't have a copy constructor then you can't accidentally call it. :)

Comments (0)

No comments yet. Start the discussion.

Comment on this issue