The main reason why this practice is somewhat suspicious, and why I'd generally recommend against it, is that users, when they call your function,
int val;
obj.my_Func(val);
may not be aware of the fact that the value of val
is in fact modified. This may be more or less obvious when the function has only one parameter and no return value other than an error code, but as soon as you have a slightly more complex function call, e.g.
int x,y,rad,len;
obj.calculate_coord(x,y,rad,len);
the intention may be to calculate rad
and len
from x
and y
, or vice versa, or something entirely different. Since the argument names are chosen by the user, and their order or types do not give any hint on which ones serve as input and which ones as output parameters, this can cause misunderstandings, hence make the code harder to maintain and give rise to bugs.
On the other hand, it is quite straight-forward to use C++ syntax to properly return not just the value or the error code, but a combination of one or more values and an error code.
In the simplest case you may use a function like this (using C++11 syntax):
std::tuple<int,int,int> my_Func(int input)
{
/* calculate.. */
return { error_code , val1 , val2 };
}
to return two values and an error code. There is no question that input
is a pure input parameter (passed by value) and the return value is complex and includes everything you might want to return.
Contrary to what some programmers may suggest, this does not usually cause a lot of unnecessary copying, even when the return value is much larger (because of return value optimization, and in C++11 because of move semantics).
There may be exceptions, especially in pre-C++11, i.e. special cases where move semantics can't be used or for some reason return value optimization doesn't apply. There may also be cases where code profiling reveals that a) the function is used extremely heavily, and b) for whatever reason, passing the output through a reference is faster. In these cases, passing an output parameter by reference may be the right technique to use.
Of course, what I said above applies only to the use of references as output parameters, i.e. as an indirect way of returning values to the user, in particular when the fact that the function modifies some of its parameters isn't made obvious by its name.
There can be many other, and valid, reasons for passing by reference, esp. by const-reference.