Thread: Vector Iterator Help

  1. #1
    Registered User (TNT)'s Avatar
    Join Date
    Aug 2001
    Location
    UK
    Posts
    339

    Vector Iterator Help

    Hi,

    Im trying to remove an element from a vector inside a loop using an iterator, which it seems I am doing incorrectly.

    Code:
    		for(vector<bomb>::iterator bm = bombs.begin(); bm!=bombs.end(); ++bm)
    		{
    		    ....
                        bombs.erase(bm);
    		}
    Looking around it seems this fails (it gives a segmentation fault) because i am using an invalidated iterator, but im not sure how to correct this?

    Thanks for any help.

    Jack
    TNT
    You Can Stop Me, But You Cant Stop Us All

  2. #2
    Registered User
    Join Date
    Nov 2006
    Posts
    519
    A vector's iterators are invalidated when its memory is reallocated. Additionally, inserting or deleting an element in the middle of a vector invalidates all iterators that point to elements following the insertion or deletion point.
    So use a container which is more friendly in this situation or stop accessing any invalidated iterator, particularly bm. showing the code of the whole loop would be helpful to answer your question in depth.

    for example, if you want to delete a number of bombs with a special property in a single loop, this could help:
    Code:
    if(...)
    {
      vector<bomb>::iterator pre = bm;
      bombs.erase(bm);
      bm = pre;
    }
    Last edited by pheres; 11-04-2007 at 02:46 PM.

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    erase returns an iterator that you should use to continue through the vector. A typical format for erasing while iterating looks like this:
    Code:
    for(vector<bomb>::iterator bm = bombs.begin(); bm!=bombs.end(); )
    {
      if (/* erase */)
        bm = bombs.erase(bm);
      else
        ++bm;
    }

  4. #4
    Registered User (TNT)'s Avatar
    Join Date
    Aug 2001
    Location
    UK
    Posts
    339
    Thanks, the entire code below, i would like to stick with the vector container if at all possible, i have modified my loop/erase code to 'attempt' to re validate the iterator, but it still doesnt work.

    Code:
    		for(vector<bomb>::iterator bm = bombs.begin(); bm!=bombs.end(); )
    		{
    			// Draw bomb
     			glRectd(bm->x1, bm->y1, bm->x2, bm->y2);
     
     			// Move bomb downards
     			bm->y1-= delta_time * BOMB_VELOCITY;
     			bm->y2-= delta_time * BOMB_VELOCITY;
     
    			// Check for impact
     			if((bm->x2 <= ship->RightX && bm->x1 >= ship->LeftX) && (bm->y2 <= ship->TopY && bm->y2 >= ship->LeftY))
     			{
    				// Impact occured
    				bm = bombs.erase(bm);	// destroy bomb
    
    				
    
     				ship->ship_destroy = true;
     				ship->lives--;
     			}
    			
    			++bm;
    		}
    This still segment faults :S

    Thanks again
    TNT
    You Can Stop Me, But You Cant Stop Us All

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    You didn't quite follow my example. Notice that in my example, ++bm is called in the else. That means it isn't called if erase is called. In your code ++bm will always be called every time through the loop, which is why it fails.

    You should only do one or the other. Either call erase and save the return value, or increment with ++.

  6. #6
    Registered User (TNT)'s Avatar
    Join Date
    Aug 2001
    Location
    UK
    Posts
    339
    That seems to have fixed the problem, thanks very much for the help, much appreciated.
    TNT
    You Can Stop Me, But You Cant Stop Us All

Popular pages Recent additions subscribe to a feed