现在的位置: 首页 > 综合 > 正文

stl vector/list如何一边遍历一边删除

2013年12月12日 ⁄ 综合 ⁄ 共 1465字 ⁄ 字号 评论关闭

有时候我们在遍历stl的容器的时候需要删除一些不符合条件的item,这时候我们就要担心iterator是不是因为原始的数据的改变而发生改变,因此往往比较容易出现一些问题,

下面比较一下list 和 vector的两种一边遍历一边删除:

    // list
    list<int> lll;
    // vector
    // vector<int> lll;
   
    lll.push_back(1);
    lll.push_back(2);
    auto tb = lll.begin(), te= lll.end();
    for(;tb!=te;){
        printf("%p", &*tb);
        printf("%p", &*(lll.end()));
        tb=lll.erase(tb);
    }

list的能正常通过运行但是vector的却有断错误,问题出在哪里呢? 问题就是在于两个的erase函数的不同

List:
This effectively reduces the list size by the number of elements removed, calling each element's destructor before.

lists are sequence containers specifically designed to be efficient inserting and removing elements in any position, even in the middle of the sequence. Compared to the other base sequence containers (vector and deque), lists are the most efficient container
erasing at some position other than the beginning or the end of the sequence, and, unlike in these, all of the previously obtained iterators and references remain valid after the erasing operation and refer to the same elements they were referring before (except,
naturally, for those referring to erased elements).

vector:
Because vectors keep an array format, erasing on positions other than the vector end also moves all the elements after the segment erased to their new positions, which may not be a method as efficient as erasing in other kinds of sequence containers (deque,
list).

This invalidates all iterator and references to position (or first) and its subsequent elements.

不难发现list erase不会改不原来的iterator, vector 就会改变,因此我们只要在代码里稍微做一点点修改就可以改正这个问题:

for(;tb!=te;)

// change to

for(;tb!=lll.end();),

另外我们也发现 vector 的 erase 需要整个vector 移动,这个代价十分高,所以尽量少用。若排序顺序不是很重要的化,可以和最后的那个item swap,然后删掉最后那个,这样可以显著的提高效率。

抱歉!评论已关闭.