Re: Unpredictable nature of increment operators
In article <g0216m$pqc$1@news.datemas.de>, v.Abazarov@comAcast.net
says...
[ ... ]
For example, it's not undefined behaviour to do
f(i++) + ++i;
IIRC, but the results are unspecified.
I believe this still gives undefined behavior. There are three sequence
points in this expression: before f is called, when f returns, and at
the end of the expression. The compiler can generate code that evaluates
the pre-increment, then the post-increment, then the function call.
There's no sequence point between the pre- and post-increment, so the
result is undefined behavior.
And if your class has the
operators ++() or ++(int) overloaded, the results are even well-
defined and predictable. For 'int' they aren't...
Well-defined but not necessarily predictable. The fact that it's a
function call imposes a sequence point as the function is called, and as
it returns -- but still doesn't require that the functions be called in
any particular order, so the value as the function is entered can be
unpredictable. For example:
#include <iostream>
class X {
int value;
public:
X() : value(0) {}
X(int v) : value(v) {}
X &operator++() {
++value;
return *this;
}
X operator+(X const &other) {
return X(value + other.value);
}
friend std::ostream &operator<<(std::ostream &os, X const &x) {
return os << x.value;
}
};
int main() {
X x, left, right;
std::cout << (left= ++x) + (right = ++x) << "\n";
std::cout << "Left = " << left << "\n";
std::cout << "Right = " << right << "\n";
return 0;
}
Now, this gives defined behavior -- regardless of the order of
evaluation, there is always a sequence point between executing the two
increment operators. Nonetheless, the compiler is free to produce code
that evaluates either the left or the right sub-expression first, so the
values of 'left' and 'right' aren't entirely predictable.
For example, using Comeau, I get Left = 1 and Right = 2. Using G++ or
Microsoft, I get Left = 2 and Right = 1.
--
Later,
Jerry.
The universe is a figment of its own imagination.