In a particle system, once particles become old enough, they need to die. Since they are stored in an std::vector the approach that works rather well in XCode is:
for(std::vector<Particle*>::reverse_iterator iter = particles.rbegin(); iter != particles.rend(); ++iter) {
(*iter)->update();
if ( (*iter)->isDead() ) {
delete (*iter);
particles.erase( --iter.base() );
}
}
After booting into Windows, and compiling in Visual Studio 2010, I found that it doesn't work: see here. As the answer itself states, this does not work for associative containers. What I find most frustrating here is that std::reverse_iterator and std::iterator behave differently:
.erasedoes not take areverse_iteratorand wants a real thing (e.g. see this)rev_it.base()call needs to be decremented in the erase call- after erasing, I need to convert the
std::iteratorto anstd::reverse_iterator
I thought of using a forward std::iterator but iterating backwards, which is a terrible idea - but the very need for iterating backwards, really, is to ensure that the loop doesn't skip neighboring members of erased particles.
What makes sense to me, though, is not iterating if the .erase() call is made:
for( std::vector<Particle*>::iterator iter = particles.begin(); iter != particles.end(); ) {
(*iter)->update();
if ( (*iter)->isDead() ) {
delete (*iter);
iter = particles.erase(iter);
} else {
++iter;
}
}
This compiles, works, and doesn't seem to be a problem. The question, though, is:
Am I overlooking something that renders this a particularly stupid idea?
(I'm sure that iter will point at the correct next value by taking advantage of the .erase() function's return value, and it seems more readable to me than --iter.base() call.)
That parenthetical aside, a Russian saying that comes to mind is "One who's been burned on hot milk blows on cold water."