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:
.erase
does not take areverse_iterator
and 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::iterator
to 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."