You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于std::list.erase()迭代器行为的困惑:为何未跳过后续元素?

关于std::list erase后迭代器遍历异常的问题

我写了removeOdd函数用来删除std::list<int>里的奇数元素。根据std::list.erase()的文档,它会返回指向被删除元素下一个元素的迭代器,我原本觉得函数会跳过这个后续元素继续遍历,但测试脚本居然通过了?后来给函数加了输出,迭代器出现了好像循环回链表的异常输出,查了文档也搞不懂,求解答。

原removeOdd函数代码:

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

修改后带输出的函数运行输出:

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


问题分析与解决

你的代码逻辑核心问题出在it++上。当你调用erase删除元素时,已经把it更新为被删元素的下一个迭代器,但循环末尾的it++会让迭代器再往后走一步,直接跳过了一个元素。测试脚本通过只是刚好测试用例没覆盖到漏删场景,但加输出后暴露了迭代器的异常——本质是迭代器越界导致的未定义行为,看起来就像循环回链表了。

正确的写法要区分两种情况:删除元素时不执行自增,仅在不删除时让迭代器前进。这里提供两种写法:

写法一:使用while循环

void removeOdd(list<int>& li)
{
    auto it = li.begin();
    while (it != li.end()) {
        if (*it % 2) {
            // erase返回下一个元素的迭代器,直接赋值继续遍历
            it = li.erase(it);
        } else {
            // 不需要删除时,手动让迭代器前进
            ++it;
        }
    }
}

写法二:调整for循环逻辑

void removeOdd(list<int>& li)
{
    // 把it++从循环头移到内部控制
    for (auto it = li.begin(); it != li.end(); ) {
        if (*it % 2) {
            it = li.erase(it);
        } else {
            ++it;
        }
    }
}

简单来说:erase返回的迭代器已经帮你定位到下一个要检查的元素,这时候直接用它继续判断就行,不需要额外自增;只有元素不需要删除时,才手动让迭代器前进,这样既不会跳过元素,也不会出现迭代器异常。

内容的提问来源于stack exchange,提问作者Teong Seng Tan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 19:06:09