iterator的陷阱

来源:互联网 发布:为什么mac不安装flash 编辑:程序博客网 时间:2024/04/30 11:03
比如某个std::vector<x>,我们对它的一个实例对象进行遍历,找到一个元素,删除之:
std::vector<x> some_vector;
for(std::vector<x>::iterator it = some_vector.begin(); it != some_vector.end(); ++it)
{
    if(...)
    {
       some_vector.erase(it);   // 这里删除了vector的一个元素,导致it失效!!循环无法继续
    }
}
想必这个错误我们都不会犯。请看下面“正确”的做法:
std::vector<x>::iterator it = some_vector.begin();
whiler(it != some_vector.end())
{
    if(...)
    {
       std::vector<x>::iterator temp = it++; // 我们先把it保存到temp,然后移动it,使其指向下一个“有效”的元素
       some_vector.erase(temp);   // “放心”地删除这个元素
    }
    else
    {
    ++it;
    }
}
呵呵,it真的“有效”吗?真的可以“放心”删除吗?仔细想想。你会犯这个错误吗?反正我今天是犯了…… :(

一般地,对于vector这样“连续存储”(有没有想到上面的代码有什么错误?:))的容器,正确的做法是:
std::vector<x>::iterator it = some_vector.begin();
whiler(it != some_vector.end())
{
    if(...)
    {
       some_vector.erase(it);   // it失效了
       it = some_vectorect.begin(); // 修正it,使其有效,然后重新开始遍历
    }
    else
    {
        ++it;
    }
}

类似地,在遍历过程中插入元素的情况也要仔细处理。