Archived

This topic is now archived and is closed to further replies.

Deleting objects in std::list

This topic is 5016 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

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;
	} 
}

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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++;
}
}

Share this post


Link to post
Share on other sites