Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

So I have a vector of bullets that show up on the screen and I do not want these bullets to live forever. I want them to "die as soon as they go off screen or collide with an enemy. How can I make sure they are removed from the array and no longer take up memory.

code:

std::vector<Bullet> bulletArray;

for(int i=0; i<bulletArray.size(); i++)
{
    bulletArray[i].MoveBullet();
    bulletArray[i].Draw();
    if(bulletArray[i].PosY<0)
    {
        //Delete object forever 
    }
}
share|improve this question
2  
Answers which will work in this situation are here: stackoverflow.com/questions/875103/… –  Trevor Powell Jan 1 '13 at 19:54
    
bulletArray.erase(enemyArray.begin() + 1); This i have tried and i saw this post but i get this error : Error 2 error C2664: 'std::_Vector_iterator<_Myvec> std::vector<_Ty>::erase(std::_Vector_const_iterator<_Myvec>)' : cannot convert parameter 1 from 'std::_Vector_iterator<_Myvec>' to 'std::_Vector_const_iterator<_Myvec>' –  Jonathan O Jan 1 '13 at 19:59
3  
You cannot erase an element of enemyArray from bulletArray. You can only erase elements of bulletArray from bulletArray, because enemyArray is not bulletArray. You can only use iterators from a particular vector to erase elements from that same vector, not any other vector. –  Trevor Powell Jan 1 '13 at 20:04
    
You are right. Thank you –  Jonathan O Jan 1 '13 at 20:14
    
@JonathanO In future please post purely C++-related questions like this on stackoverflow.com, not here. Thanks. –  Nick Wiggill Jan 2 '13 at 13:48

2 Answers 2

up vote 9 down vote accepted

There are two ways to do it:

  1. You can simply remove object i from the vector using bulletArray.erase(bulletArray.begin() + i) and then i-- to process everything for the new bullet in i'th position. But this way vector will move all the object after the that specific bullet, meaning this kind of removal is O(bulletArray.size()).

  2. But usually order of the bullets is not important, so you can simply put the last bullet in the i'th cell, and only remove it's spot. This way it's much more faster since these operations are O(1). And it's implemented as bulletArray[i] = bulletArray.back(); bulletArray.pop_back(); i--; again you need to decrement i by one to check this new object in this i'th position in the next loop.

share|improve this answer
    
In #2, you should use swap rather than a copy if bullets are moderately complex objects --- it is much faster if there is a string in it, for instance. Actually, it looks like a vector is the wrong data structure for this job. –  Federico Poloni Jan 2 '13 at 0:19
    
@FedericoPoloni using swap will result in two copies, which is much more expensive to one copy! besides, using vector is not a bad idea in general, except std::vector is slow. –  Ali.S Jan 2 '13 at 0:26
    
Good point. According to how swap and the copy constructor are implemented, either choice could be faster. We cannot say more without knowing what a bullet is. I think that this is the exact problem that is solved by the introduction of move constructors in C++11. If the OP is willing to use C++11 extensions, this looks like the right tool for the job. –  Federico Poloni Jan 2 '13 at 10:39

In general, I find that it's a good idea to add a flag (normally I call this "dead") to the objects.

Then you can do this (in pseudo-pythonic code):

// Processing
for obj in my_list:
  if obj has hit enemy:
    obj.dead = true
  if obj outside play area:
    obj.dead = true
// Rendering (at some different point)
for obj in my_list:
  render somehow

Then you can use the std::remove_if higher-order function (in algorithms) to remove the ones with the "dead" flag set. Remember to use std::erase to truncate the vector to the right point.

The main advantage of using this remove_if/erase is that it avoids problems when trying to remove elements while iterating the list.

Additionally, sometimes you may want to remove object X while processing object Y (in collision detection, such situations are normal) - we can do this easily without breaking any iterator objects.

(Note that iterator objects are normally only valid as long as no new elements are added or removed. Especially for std::vector)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.