Jump to content
  • Advertisement
Sign in to follow this  
DMINATOR

removing std::list elements, how to do it right ?

This topic is 4726 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi. Well I am still learning some of the features of the standard library. Here is one problem I have:
#include <iostream>
#include <list>


using namespace std;
int main()
{
	//add some elements to the list
	list<int> numbers;

	numbers.push_back(10);
	numbers.push_back(20);
	numbers.push_back(30);


	list<int>::const_iterator it;
	int val;

	//here is the lopp
    for( it = numbers.begin(); it != numbers.end() ; it++)
	{
        val = (*it);

		cout << "value= " << val << endl;

		//remove the value
		numbers.remove( val );
	}

	return 0;
}

As you can see iterator gets messed up, if some value is removed from the list. So how you are doing it the right way ? Thank you for your help.

Share this post


Link to post
Share on other sites
Advertisement
I'd do this:

it = numbers.begin();
while(it != numbers.end())
{
val = (*it);
cout << "value= " << val << endl;
//remove the value
numbers.remove( val );
it = numbers.begin();
}

Share this post


Link to post
Share on other sites
it = numbers.begin();
while(it != numbers.end())
{
if( must_remove(it) )
{
it = numbers.erase(it);
}
else
{
++it;
}
}

Share this post


Link to post
Share on other sites
Why complicate things by outputting and removing in the same loop? Just print the elements and then call clear().

Share this post


Link to post
Share on other sites
EDIT: Wow - I'm slow [smile]
Don't do it this way - removing an iterator invalidates all iterators that follow it.
There are a few ways to get around this problem. One is to use std::remove or std::remove_if, the other is to use two loops:


std::vector<int> removed;
for( it = numbers.begin(); it != numbers.end() ; it++)
{
val = (*it);

cout << "value= " << val << endl;

//remove the value
removed.push_back( val );
}
while ( !removed.empty() )
{
numbers.remove( removed.back() );
removed.pop_back();
}




HTH,
Pat.

Share this post


Link to post
Share on other sites
darookie: Or, as Fruny showed, just use the return value of remove erase() :)

[Edited by - Sharlin on January 1, 2006 7:02:08 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by darookie
EDIT: Wow - I'm slow [smile]
Don't do it this way - removing an iterator invalidates all iterators that follow it.

Not in the case of lists. Vectors, yes. But not lists, or sets, or maps. deques are even worse than vectors...even iterators before the current one are invalidated if you remove from the middle. That's all I can think of off hand.

CM

Share this post


Link to post
Share on other sites
Yes, but removal *does* invalidate iterators pointing to the removed element itself, so after removal you can't continue iteration with the iterator passed to remove erase(). Instead, you'd use the iterator returned from the call.

EDIT: SiCrane's right, of course.

Share this post


Link to post
Share on other sites
Thank you. Thats good suggestions.

Ok but what to do if list element is removed in some other place.
let's imagine (it) is iterator of some class list which has Update method. The Update may remove the class from the list.



for( it = numbers.begin(); it != numbers.end() ; it++)
{

(*it).Update();
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!