There’s been some debate going on in this question about whether the following code is legal C++:
std::list<item*>::iterator i = items.begin(); while (i != items.end()) { bool isActive = (*i)->update(); if (!isActive) { items.erase(i++); // *** Is this undefined behavior? *** } else { other_code_involving(*i); ++i; } }
The problem here is that erase() will invalidate the iterator in question. If that happens before i++ is evaluated, then incrementing i like that is technically undefined behavior, even if it appears to work with a particular compiler. One side of the debate says that all function arguments are fully evaluated before the function is called. The other side says, ‘the only guarantees are that i++ will happen before the next statement and after i++ is used. Whether that is before erase(i++) is invoked or afterwards is compiler dependent.’
I opened this question to hopefully settle that debate.
Quoth the C++ standard 1.9.16:
So it would seem to me that this code:
is perfectly legal. It will increment
iand then callfoowith the previous value ofi. However, this code:yields undefined behavior because paragraph 1.9.16 also says: