First, as already said, don't do freeFunct3
if the semantics of the free function is to only modify its "own" object.
Second, there are differences between freeFunct1
and freeFunct2
, relating to move optimization [C++11], exception safety, and potentially code size.
With freeFunct2
(taking by reference-to-const):
- It will always construct a new copy of the argument, never move it [C++11].
- If the copy construction of
A
throws an exception, it will throw inside the body of the function. - If
A
's copy constructor is inlined (and the function is not), it will be expanded once, inside the body of the function (even if the function is called from multiple different places).
With freeFunct1
(taking by value):
- [C++11] You can avoid a copy if
A
has a move constructor and you pass an rvalue (e.g. callfreeFunct1(A(args))
). - If the copy (or move) construction of
A
throws an exception, it will throw at the call site. - If
A
's copy (or move) constructor is inlined, it will be expanded multiple times, at each call site.
Alternatively, you can overload on lvalue/rvalue reference to avoid unnecessarily copying rvalues:
void freeFunct4(const A& a){
A b = a;
b.doStuff();
}
void freeFunct4(A&& a){
a.doStuff();
}