Others have covered the case where A
might not have a cheap move constructor. I'm assuming your A
does. But there is still one more situation where you might want to pass in an "out" parameter:
If A
is some type like vector
or string
and it is known that the "out" parameter already has resources (such as memory) that can be reused within f
, then it makes sense to reuse that resource if you can. For example consider:
void get_info(std::string&);
bool process_info(const std::string&);
void
foo()
{
std::string info;
for (bool not_done = true; not_done;)
{
info.clear();
get_info(info);
not_done = process_info(info);
}
}
vs:
std::string get_info();
bool process_info(const std::string&);
void
foo()
{
for (bool not_done = true; not_done;)
{
std::string info = get_info();
not_done = process_info(info);
}
}
In the first case, capacity will build up in the string
as the loop executes, and that capacity is then potentially reused on each iteration of the loop. In the second case a new string
is allocated on every iteration (neglecting the small string optimization buffer).
Now this isn't to say that you should never return std::string
by value. Just that you should be aware of this issue and apply engineering judgment on a case by case basis.