STL : List使用时应注意的问题

这篇文章所述只是本人遇到的问题,仅供参考。

#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()就能安全有效地进行该项操作)。

原文地址:https://www.cnblogs.com/ll-10/p/5461481.html