这篇文章所述只是本人遇到的问题,仅供参考。
#include<list> #include<iostream> using namespace std; class Foo { public: Foo(int i) {m_iData = i;} void setData(int i ) {m_iData = i;} int GetData() {return m_iData;} private: int m_iData; }; // 为了提高可读性,定义容器和迭代器的名字 typedef list<Foo*> FooList; typedef FooList::iterator FooListItor; void main() { FooList c; // 创建一个链表容器 //将三个不同的元素填入链表中 c.push_back(new Foo(1)); c.push_back(new Foo(2)); c.push_back(new Foo(3)); //迭代遍历链表 for(FooListItor itor = c.begin();itor != c.end();) { if((*itor)->GetData() == 2) { delete (*itor); itor = c.erase(itor); } else ++itor; } //确保所有的对象被删除,链表不会自动完成该项任务 for(FooListItor itor2 = c.begin(); itor2 != end();++itor2) delete (*itor2); }
使用指针指向动态分配内存的结构或对象时,有几件事情需要注意。
1. 你要负责在使用完对象后释放所有分配的内存。容器并不知道将使用何种类型,所以它们不可能帮你自动释放内存。
2. 许多运算可能会失败,这是因为它们直接对对象或结构的指针进行操作,而不是对对象或结构本身。比如链表的sort()函数,它使用<运算符来比较值并以此结果进行排序。就算运算符对类Foo是合法的,但链表的排序仍是按照指针的实际值而不是对象中数据的值。因而有必要设计自己的比较运算符,在比较之前先对指针解引用。
3.记住,复制容器时,复制的仅仅是指针而不是对象。如果产生了重复的指针,将极难确定哪一个对象需要删除。解决办法是使用智能指针(smart pointer),或避开容器间复制元素的STL的例程或算法。
4.注意,在迭代遍历链表的时候,从链表中删除元素要非常小心。因为删除当前指向的元素将导致迭代器失效,所以你必须确保正确使用erase()函数的返回值,它是这个函数将检索出的容器中的下一个合法位置,通过将这个返回值分配给老的迭代器,我们就跳过了非法位置。但是这又给我们带来了新的问题。当for循环在循环结束处试图对迭代器递增,由于我们已经用erase()将迭代器递增到了下一个位置,因此就会出现问题。为了解决这个问题,我们将递增运算从for循环体移到了循环中的条件选择语句内,在元素没有删除时才进行递增。(一般来说,最好使用算法从容器中删除元素,而不是手工迭代来做,如算法remove_if()就能安全有效地进行该项操作)。