I am calling the factorial function defined in the following manner by reference.
int factorial(int &n) {
n--;
if (n>0) return factorial(n)*(n+1);
else return 1;
}
when I pass the value 5 it returns the value 1 as I'd expected. But when I define the factorial function in the following way it returns the factorial of 5 that is 120.
int factorial(int &n) {
n--;
if (n>0) return (n+1)*factorial(n);
else return 1;
}
I conjectured that the expression is evaluated in linear order and when a function is invoked in the expression all the values of local variables and the component expressions that have been evaluated so far in the original expression are stored and when the function returns control back to the caller these values that are retained are used in computation of the expression and not their modified values.
Is my hypothesis correct? Kindly enlighten me.
I conjectured that the expression is evaluated in linear order [...]
Yes and no. The order of evaluation is typically done in linear order (either first to last or last to first), but is unspecified. When you write factorial(n)*(n+1)
, the compiler is allowed to evaluate (n+1)
first or factorial(n)
first. Different compilers will do it differently. Moreover, different versions of the same compiler could even change orderings, so that's not something you should ever rely on. The standardese is in [intro.execution]:
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [...] If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, and they are not potentially concurrent (1.10), the behavior is undefined.
(The exceptions are things like &&
, ||
, ,
, and ?:
)
In this case, you can easily avoid relying on the order dependency completely by just removing the reference:
int factorial(int n) {
if (n>0) return factorial(n-1)*(n);
else return 1;
}
Now factorial(n-1) * n
and n * factorial(n-1)
, regardless of which order they're evaluated in, both work and give you the same correct answer. This also has the added benefit that nobody would expect factorial
to actually modify its argument anyway:
int i = 6;
int f = factorial(i);
// now i is 1??
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With