Thread: erasing elements from a boost::ptr_vector (boost n00b)

  1. #1
    Registered User
    Join Date
    Jan 2003
    Posts
    118

    erasing elements from a boost::ptr_vector (boost n00b)

    I'm having trouble ereasing elements from the ptr_vector, sometimes it crashes my program, here is the method where it happens

    Code:
    void Juego::checkState()
    {
        Bullet *b;
        boost::ptr_vector<Entity>::iterator iter;
        
        for (int i = 0; i < entities.size(); i++)
        {
            if (entities[i].getInst() == inst_bullet)
            {
                b = (Bullet*)&entities[i];
                if (b->getDestroy())
                {
                    iter = entities.begin();
                    for (int j = 0; j < i; j++)
                    {
                        iter++;
                    }
                    entities.erase(iter);
                }
            }
        }
    }
    Here is what I'm trying to do:

    Go through the ptr_vector of Entities and if one is a Bullet (which is derived from entity) I call getDestroy() (which will tell me if the bullet must be destroyed, and is not inherited from Entity) if the bullet must be destroyed I erase that bullet from the vector.

    As you can see I'm not familiar at all with iterators and boost, how should I do what I want?
    Why drink and drive when you can smoke and fly?

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I'm not sure why it would crash. One problem I see is thet you are skipping over some values in your loop. If i is 3 and you erase that value, then all the elements after it will be moved over, and a new element will be put in the 3 spot. In the next iteration of the loop i will be 4 and will never check the element that got moved into the 3 spot.

    Also, the entire block of code inside the if (b->getDestroy()) can be changed to entities.erase(entities.begin() + i);

    Another thing that doesn't look right is b = (Bullet*)&entities[i]; This is generally an indication of bad design. Your Entity class should have the virtual getDestroy() function that you can call without casting directly to a Bullet.

    Normally, you would just use iterators to iterate over the whole thing. Assuming thet getDestroy is virtual in Entity:
    Code:
        boost::ptr_vector<Entity>::iterator iter = entities.begin();
        
        while (iter != entities.end())
        {
            if (iter->getInst() == inst_bullet && iter->getDestroy())
            {
                iter = entities.erase(iter);
            }
            else
            {
                ++iter;
            }
        }
    I can't think of why any of these things would cause a crash, but they are worth looking into. Also make sure Entity has a virtual destructor.
    Last edited by Daved; 04-04-2006 at 11:38 AM.

  3. #3
    Registered User
    Join Date
    Jan 2003
    Posts
    118
    Thanks a bunch Daved, as always you are the man.

    Especially thanks for the last comment about making sure the destructor was virtual, it got me checking and I discovered that under certain circumstances de destructor would try to delete a pointer which didn't point to anything causing the program to crash.
    Why drink and drive when you can smoke and fly?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. using realloc for a dynamically growing array
    By broli86 in forum C Programming
    Replies: 10
    Last Post: 06-27-2008, 05:37 AM
  2. Shifting elements in an Array
    By mmarab in forum C Programming
    Replies: 5
    Last Post: 12-10-2007, 12:11 PM
  3. Randomly rearranging the elements in a vector
    By Signifier in forum C++ Programming
    Replies: 11
    Last Post: 08-01-2007, 12:21 PM
  4. way to check 3 elements of array and set 4th
    By Syneris in forum C++ Programming
    Replies: 3
    Last Post: 01-09-2006, 11:30 AM
  5. Replies: 2
    Last Post: 08-03-2003, 10:01 AM