Deleting objects in std::list

Started by
2 comments, last by EGD Eric 20 years, 1 month ago
I''ve been trying to delete objects in std::list, but it never seems to work right. In the following example, I try to delete all the "dead" objects in a list by looping through them and using remove on the "dead" ones. After deleting the dead object, the next object in the loop causes a crash, as though I were trying to access a NULL pointer.

#include <iostream>

using std::cout;
using std::endl;

#include <list>
#include <algorithm>
#include <afxwin.h>
#include <fstream>
using std::ostream;
using std::istream;
using std::ofstream;

using std::list;
using std::fstream;
using std::ios;

#define SIZE 5



class Example
{
public:
	Example() {}
	Example(int Value, bool bDead = false) {value = Value; dead =  bDead;}
	int getValue() {return value;}
	void setValue(int newValue) {value = newValue;}
	bool dead;
private:
	int value;

};

//typedef for easier readability

typedef list<Example *> ExampleList;
typedef	list<Example *>::iterator exItor;


void printList(std::list< Example * > &listRef);
void saveList(std::list< Example * > &listRef, char* filename);
void loadList(std::list< Example * > &listRef, char* filename);


void main()
{
	
	ExampleList theList; //list of example classes

	ExampleList secondList;
	Example* ptr;


	//Populate the list

//	loadList(theList, "Example.txt");

	theList.push_back(new Example(5));
	theList.push_back(new Example(4));
	theList.push_back(ptr = new Example(3, true));
	theList.push_back(new Example(2));
	theList.push_back(new Example(1));

	secondList = theList;
	printList(theList);
	
	list<Example *>::iterator it;
	cout << "Deleting dead items:" << endl;
	for(it = theList.begin(); it != theList.end(); it++)
	{
		if((*it)->dead == true)
			theList.remove(*it);
	}

	printList(theList);
	cout << "Here''s the second:\n";
	printList(secondList);
}


void printList(std::list< Example * > &listRef)
{

	if(listRef.empty())
		cout << "List is empty.\n";

	else
	{
	//	std::ostream_iterator< T > output(cout, " "); //declare output iterator

	//	std::copy(listRef.begin(), listRef.end(), output); //copy to output stream


		std::list< Example * >::iterator it;

	
		for(it = listRef.begin(); it != listRef.end(); it++)
		{
			cout << (*it)->getValue() << endl;
		}
		cout << endl;
	} 
}

Advertisement
The loop you're using to remove dead items is error-prone. The problem looks like you're trying increment an invalidated iterator. Instead consider using the std::list::remove_if() member function.

edit: unless you're using MSVC 6 which doesn't properly support the remove_if() member function for std::list objects. In that case you'd need to do something like:
  for(it = theList.begin(); it != theList.end(); ) {    if((*it)->dead == true) {      it = theList.erase(it);    } else {      ++it;    }  } 


[edited by - SiCrane on March 21, 2004 4:22:22 PM]
A less elegant but more simple (and erase_if-free) solution might look a bit like...

list<Example*>::iterator thisOne = ExampleList.begin(),    max = ExampleList.end(),    lastOne = thisOne;lastOne--;while (thisOne != max){   if (*thisOne->dead)   {      ExampleList.erase(thisOne);      thisOne = lastOne;      thisOne++;   }   else   {      lastOne = thisOne;      thisOne++;   }}
Thanks for the tip. It works.

This topic is closed to new replies.

Advertisement