How to not invalidate an iterator used to iterate through an STL container while removing (or deleting) its elements.

By lxcid

Many of us who use STL containers and their iterators may need to delete elements while iterating. An example case is:

Delete the game objects that are dead.

To fulfil the above case, you need to iterate through game objects, check their health and delete them if they are dead. The pseudocode would be:

FOREACH game object in game object list
	IF game object's health is less than or equal to zero
		REMOVE game object from game object list
		DELETE game object

Many of us will write the above pseudocode this way:

std::vector< GameObject * > gameObjectList; ///< Game object list

// Throw in some zombies.
gameObjectList.push_back( new GameObject("Zombie01") );
GameObject * zombie02 = new GameObject("Zombie02");
zombie02->kill(); // Kill the zombie02.
gameObjectList.push_back( zombie02 );
gameObjectList.push_back( new GameObject("Zombie03") );
gameObjectList.push_back( new GameObject("Zombie04") );

// Initialize the the iterator.
std::vector< GameObject * >::iterator iEnd = gameObjectList.end();
std::vector< GameObject * >::iterator i = gameObjectList.begin();

while ( i != iEnd )
{
	GameObject * gameObject = * i;
	if ( gameObject.isDead() )
	{
		gameObjectList.erase( i );
		delete gameObject;
	}
	i++;
}

The above code seems perfectly fine but when executed you will notice that after deleting zombie02, the iterator will be invalidated and crash at i++. This is because i is a reference to the element previously storing zombie02 which is now removed. The solution is to make i set to the next iterator after zombie02 (which in this case is zombie03). STL containers erase function will return the next iterator after the one specified in its parameter. So the correct code would look like this now.

while ( i != iEnd )
{
	GameObject * gameObject = * i;
	if ( gameObject.isDead() )
	{
		i = gameObjectList.erase( i );
		delete gameObject;
	}
	else
	{
		i++;
	}
}

P.S. I may update this post with more solutions when I have the solution and time.

Tags: , , , , , , , , , ,

2 Responses to “How to not invalidate an iterator used to iterate through an STL container while removing (or deleting) its elements.”

  1. psycho Says:

    found by google, thanks for clean explanation of this obvious solution..

  2. lxcid Says:

    I’m glad it helps you. I have plans to rewrite this article in coming weeks. Providing another solution I found and about deleting the elements in reverse order. :)

Leave a Reply