std::vector iterator problems

This is a discussion on std::vector iterator problems within the C++ Programming forums, part of the General Programming Boards category; I have this list which contains a couple of objects: ships and asteroids. To update all positions and process keys, ...

  1. #1
    return 0;
    Join Date
    Jan 2005
    Location
    Netherlands
    Posts
    89

    std::vector iterator problems

    I have this list which contains a couple of objects: ships and asteroids. To update all positions and process keys, I have this code:

    Code:
    std::vector<SolidObject *>::iterator item = m_objects.begin();
    
    while(item != m_objects.end()) {
        if((*item)->Update() == false) {
            delete (*item);
            item = m_objects.erase(item);
        }
        else {
            item++;
        }
    }
    This works fine, as long as my ship doesn't fire a bullet. When it does, a new object is added to m_objects:

    Code:
    game->AddObject(new Bullet(m_pos, m_move, m_direction, 5.0));
    
    // AddObject is an inline function:
    // inline void PlayingState::AddObject(SolidObject *item) {
    //    m_objects.push_back(item);
    // }
    AddObject is called in the ship's Update(), so something like this happens:

    Code:
    list: Ship, Asteroid, Asteroid, Asteroid
    iterating through list:
       - Ship->Update()
            - A bullet is added to the list
            - New list: Ship, Asteroid, Asteroid, Asteroid, Bullet
       - SEGMENTATION FAULT
    The segmentation fault occurs right after I fire a bullet, when (*item)->Update() is called.

    I guess the problem is that the list gets altered while I'm iterating through it. Any ideas on how to fix this?

  2. #2
    Registered User
    Join Date
    Dec 2004
    Location
    UK
    Posts
    109
    If I remember correctly any modification to a vector invalidates all iterators.
    My guess is that the segfault comes from calling item++ after update returns since item is no longer valid

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,461
    If I remember correctly any modification to a vector invalidates all iterators.
    Not quite. In this case, only iterators that point to elements following the erased element are invalidated.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Registered User
    Join Date
    Jan 2005
    Posts
    7,317
    You could make a copy of the vector before running the Update loop so that you don't get affected by new objects. The next time through the new objects will be in the vector and get updated.

    You could also use a temporary buffer to hold the added objects until a round of updating is done so that the additions don't invalidate iterators. Then when the updates are done you copy the new objects in the buffer into the m_objects list.
    Last edited by Daved; 05-15-2006 at 04:50 PM.

  5. #5
    Registered User
    Join Date
    Dec 2004
    Location
    UK
    Posts
    109
    My bad. Iterators are invalidated if the vector is reallocated however, which could occur when push back is called.

Popular pages Recent additions subscribe to a feed

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21