std::list.erase() 似乎正在重新排列列表的元素

问题描述 投票:0回答:1

考虑以下函数

void removeOdd(list<int>& li)
{
    for(list<int>::iterator it=li.begin(); it!=li.end(); it++)
    {
        if((*it)%2) it = li.erase(it);
    }
}

根据我对列表的理解,其中返回值是一个“指向函数调用删除的最后一个元素后面的元素的迭代器”,

std::list.erase() documentation

removeOdd() 函数应该在删除元素后忽略该元素并继续遍历列表。

但是,当链接到此测试脚本时

#include <list>
#include <vector>
#include <algorithm>
#include <iostream>
#include <cassert>
using namespace std;

void test()
{
    int a[9] = { 5, 2, 8, 9, 6, 7, 3, 4, 1 };
    list<int> x(a, a+9);  // construct x from the array
    assert(x.size() == 9 && x.front() == 5 && x.back() == 1);
    removeOdd(x);
    assert(x.size() == 4);
    vector<int> v(x.begin(), x.end());  // construct v from x
    sort(v.begin(), v.end());
    int expect[4] = { 2, 4, 6, 8 };
    for (int k = 0; k < 4; k++){
        assert(v[k] == expect[k]);
    }
}
int main()
{
    test();
    cout << "Passed" << endl;
}

它过去了。此外,将removeOdd()修改为

void removeOdd(list<int>& li)
{
    for(list<int>::iterator it=li.begin(); it!=li.end(); it++)
    {
        if((*it)%2){
            cout << *it << " ";
            it = li.erase(it);
            cout << *it << endl;
        } 
        else cout << *it << endl;
    }
}

并在我的 WSL 实例上运行整个脚本(使用 g++ 编译),会产生以下输出:

5 2
8
9 6
7 3
4
1 5
2
8
6
3 4
Passed

我是否遗漏了某些内容,或者列表迭代器是否循环回到列表中?

我尝试在线阅读有关 std::list.erase() 和随机访问迭代器的文档,但仍然无法理解上述行为。

c++ list stl erase
1个回答
0
投票

removeOdd 
中,即使删除项目,也会增加
it
。您只需要为不删除的项目增加它,例如:

void removeOdd(list<int>& li)
{
    for(list<int>::iterator it = li.begin(); it != li.end(); )
    {
        if (*it % 2) it = li.erase(it);
        else ++it:
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.