1 2 3 4 5 6
|
for (vector<Bullet>::iterator it = bullets.begin(); it != bullets.end(); ++it){
it->move();
if (hasLeftScreen(it->getPoint())){
it = bullets.erase(it);
}
}
|
erase() will return the iterator to the element after the one you just erased.
So if you have a vector that contains {0,1,2,3}, and you erase() the 2, your new vector will be {0,1,3} with the iterator pointing to the 3 element.
Your problem with the above for loop is that erase kind of increments your iterator for you -- whereas in your for loop you are manually incrementing. So take a look what happens when you erase the last element in the vector:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
// bullets = {0,1,2,3}
//
// Bullet 3 has left the screen, so you erase it.
it = bullets.erase(it);
// now:
// bullets = {0,1,2}
// it = bullets.end() (the element after the erased '3')
// then, when your loop finishes
++it;
// now:
// it = bullets.end()+1 -- OUT OF BOUNDS
|
Now your loop will keep going because it != end(), and any time you try to dereference it, you go out of bounds, possibly causing a crash.
Your second loop fixes this by only incrementing when you don't erase.
For this reason, loops that iterate over elements while erasing some of them are typically done with while loops, and not with for loops:
1 2 3 4 5 6 7 8
|
auto it = bullets.begin();
while( it != bullets.end() )
{
if( ... )
it = bullets.erase(it);
else
++it;
}
|