The following has unspecified results because evaluation order is unspecified:
std::string f() {
std::cout << "f()";
return "";
}
std::string g() {
std::cout << "g()";
return "";
}
int main() {
std::cout << f() << g();
}
// Output: "f()g()" or "g()f()".
To the best of my knowledge, though, it’s not invoking undefined behaviour.
However, modifying a variable twice between sequence points is definitely UB, e.g.:
int main() {
int x = 0;
std::cout << x++ << x++;
}
Now, does that rule refer only to the current scope, or would the following also be UB?
int foo() {
static int x = 0;
x++;
return x;
}
int main() {
std::cout << foo() << foo();
}
// Output: "12" or "21", or is it undefined?
The reason I ask is that my GCC 4.7.0 20111217 doesn’t warn on snippet 3, but (of course) will on snippet 2.
Both calling a function and returning from a function are sequence
points, so nothing you do in one function can conflict with what you do
in another (even if the order in which the functions are called is
unspecified).
Note that in this regard, user defined operator overloads are functions,
and introduce sequence points that wouldn’t be present for built in
types. So that something like
cout << i++ << i++isn’t undefinedbehavior if
iis a user defined type (e.g. an enum with a user definedoperator++). (The order is still unspecified, however, and justbecause the behavior is defined doesn’t mean that the code is readable
or recommendable.)