Overloaded operators are essentially functions with a different call syntax. Replace operator<< with a hypothetical function f and it might look like this:
Code:
f(f(f(f(cout, ++i), ++i), --i), endl)
Now the inner f needs to be called before an outer f (and therefore cout prints things in the correct order), however a right-hand argument may-be evaluated before an inner f is called (since the order of evaluation of arguments is unspecified).
Hence the output of the program is undefined (and GCC 4.4 issues a warning saying so).
--------
So the point is: things are printed in the correct order, but subexpressions are evaluated in an unspecified order. Here's an example, I get the three functions called in reversed order:
Code:
#include <iostream>
#include <vector>
using namespace std;
vector<char> calls;
char a() { calls.push_back('a'); return 'a'; }
char b() { calls.push_back('b'); return 'b'; }
char c() { calls.push_back('c'); return 'c'; }
int main()
{
cout << "Function results: " << a() << b() << c() << '\n';
cout << "Functions were called in this order: ";
for (unsigned i = 0; i != calls.size(); ++i) {
cout << calls[i];
}
cout << '\n';
}