When should I declare my function as:
void foo(Widget w);
as opposed to
void foo(Widget&& w);?
Assume this is the only overload. No templates involved. Assume that the function foo requires ownership of the Widget (e.g. const Widget& is not part of this discussion).
What is the performance characteristics difference? What am I telling users in my interface?
Things that my colleagues and I have already thought of:
The rvalue reference parameter forces you to be explicit about copies. The caller is responsible for making an explicit copy and then passing it in with
std::movewhen you want a copy. In the pass by value case, the cost of the copy is hidden://If foo is a pass by value function, calling + making a copy: Widget x{}; foo(x); //Implicit copy //If foo is a pass by rvalue reference function, calling + making a copy: Widget x{}; //foo(x); //This would be a compiler error auto copy = x; //Explicit copy foo(std::move(copy));The rvalue reference parameter means that you may move the argument, but does not mandate it. It is possible that the argument you passed in at the call site will be in its original state afterwards. Pass by value, if you move into it, you must assume that a move happened.
- Assuming no elisions, a single move constructor call is eliminated with pass by rvalue.
- The compiler has better opportunity to elide copies/moves with pass by value. Can anyone substantiate this claim? Preferably with a link to gcc.godbolt.org showing optimized generated code from gcc/clang rather than a line in the standard. My attempt at showing this was probably not able to successfully isolate the behavior: https://godbolt.org/g/4yomtt
Aucun commentaire:
Enregistrer un commentaire