当前位置:C++技术网 > 资讯 > vector遍历时删除元素后崩溃分析

vector遍历时删除元素后崩溃分析

更新时间:2017-07-16 11:35:13浏览次数:1+次

        先来看一段代码:

    

#include <vector>
using namespace std;

int main()
{
    vector<int> v_list;
    vector<int>::iterator it;

    v_list.push_back(1);
    v_list.push_back(2);
    v_list.push_back(3);

    for (it=v_list.begin();it!=v_list.end();++it)
    {
        if (*it=2)
            v_list.erase(it);
    }

    return 0;
}
     这是一段vector容器的使用代码。代码很简单,看上去也没有什么问题,但是运行后会崩溃,提示:

    

    vector遍历时删除元素后崩溃分析

        出现错误的时候,不要慌,不要急着关闭错误提示。来看看错误提示是什么意思。

        Expression:vector iterator not incrementable

        表达式:vector容器的迭代器不能递增。

        我们在循环里使用了迭代器来遍历容器,当找到了元素值为2时将其删除。这个应用非常常见。删除了元素之后,就发生了错误。

        在删除之前,it迭代器是按照一个顺序来遍历vector的。然而当一个元素被删除后,这种顺序就被打乱了。也就导致迭代器递增出了问题。我们原先的递增是按照未删除之前的顺序来遍历的,现在我们删除了元素,自然要重新遍历了。所以,此时你让循环继续往后走,也就是还是按照之前的顺序遍历,自然就不合理了。所以,在删除了元素之后,我们就需要重新遍历容器了。

        所以,我们在删除之后,重新用容器的开始元素来给迭代器赋值,重新遍历。所以代码修改如下:

    

#include <vector>
using namespace std;

int main()
{
    vector<int> v_list;
    vector<int>::iterator it;

    v_list.push_back(1);
    v_list.push_back(2);
    v_list.push_back(3);

    for (it=v_list.begin();it!=v_list.end();)
    {
        if (*it==2)
        {
            v_list.erase(it);
            it = v_list.begin();
            continue;
        }
        ++it;//不要放在for最后递增,否则continue后会递增一次而跳过新的开头
     }

    return 0;
}
     continue执行之后,会执行for循环里面最后一个表达式,如果迭代器在里面自增,则会导致后续的迭代器值会跳过第一个元素,所以才把迭代器自增放在你看到的这个位置。

    

        当然,如果你再深入一点,所谓的元素顺序,其实并不完全准确,更应该是迭代器对容器的遍历顺序。这里我们只是展示这样一个示例,使用时注意就行了。如果有兴趣,可以更加深入的学习STL。