Consider the following code:
struct S{
int a, b;
S() : a(0), b(10) {}
};
S operator + (const S& v, int n){
S r = v;
r.a += n;
return r;
}
S operator - (const S& v, int n){
S r = v;
r.b -= n;
return r;
}
S v = S() + 1 - 1;
Is it possible that S() + 1 - 1
will be optimized to S()
?
How does a compiler even determines when this kind of things can be optimized?
No, a compiler is not allowed to optimize
S() + 1 - 1
into
S()
because those two expressions are not equivalent for your class S
.
Even though it might be non-idiomatic, it's completely valid for S
to be written as you have done, in a way that operator+
and operator-
don't cancel each other out (in your case, by modifying different member variables in the 2 operators).
The compiler is required to evaluate S() + 1
before using that result in the evaluation of - 1
, and is only allowed to optimize that expression if it can prove that the resulting expression would be the same. In other words, the program must follow the as-if rule. Obviously, in this case the results would be different, and so the optimization is not allowed.
By the same token, if the compiler can see that an expression, and this can be any expression at all, is equivalent to some other expression, then it is allowed to optimize it as much as it wants. But again, the compiler must adhere to the as-if rule, i.e. the resulting program must behave exactly as if none of those optimizations were ever made at all.
Note that while your implementation of S
is valid according to the language rules, it is quite strange, and will surprise users of the class. I suggest only doing that for types that are very clearly domain specific, and where users of the type naturally expect that +
and -
are not necessarily inverses of each other.
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