C++ for_each传lambda删除vector小于10元素结果异常问题
问题根因分析
你的代码存在两个核心错误,直接导致部分小于10的元素残留:
- 遍历过程中修改容器会导致迭代器失效,遍历跳元素
std::for_each是基于传入的初始迭代器范围按顺序步进遍历的,而vector是连续存储容器,调用erase删除元素后,被删位置之后的所有元素都会向前移动,此时for_each持有的迭代器已经失效,下一次步进会直接跳过被前移到当前位置的元素,根本不会对这些被跳过的元素做判断。 - 删除逻辑和遍历逻辑耦合,重复全容器扫描效率极低且逻辑错误
你在lambda里每遇到一个小于10的元素x,就全容器扫描删除所有等于x的元素,这个操作本身就会打乱容器内的元素位置,和外层的for_each遍历完全冲突,进一步加剧了元素漏判的问题。
为什么输出正好是10 8 5 6 4 77 15
走一遍代码执行流程就能完全对应结果:
- 初始容器:
[10,3,8,2,5,9,6,7,4,1,77,15] - for_each第一个元素是10,不满足<10,迭代器后移
- 第二个元素是3,满足<10,全容器删3后容器变为
[10,8,2,5,9,6,7,4,1,77,15],迭代器失效后直接后移一位,跳过了刚移到当前位置的8,指向元素2 - 遇到元素2,全容器删2后容器变为
[10,8,5,9,6,7,4,1,77,15],迭代器后移跳过5,指向元素9 - 遇到元素9,全容器删9后容器变为
[10,8,5,6,7,4,1,77,15],迭代器后移跳过6,指向元素7 - 遇到元素7,全容器删7后容器变为
[10,8,5,6,4,1,77,15],迭代器后移跳过4,指向元素1 - 遇到元素1,全容器删1后容器变为
[10,8,5,6,4,77,15],迭代器再后移就到了容器末尾,遍历直接结束 - 所有被跳过的8、5、6、4全部残留,就得到了你看到的输出结果。
正确实现方式
删除vector中满足条件的元素,直接使用标准库的erase-remove_if惯用法即可,不需要外层套for_each,既没有迭代器失效问题,效率也更高:
#include<iostream> #include<vector> #include<algorithm> int main(){ std::vector<int>vec{10,3,8,2,5,9,6,7,4,1,77,15}; // 一行代码完成所有小于10元素的删除 vec.erase(std::remove_if(vec.begin(), vec.end(), [](int x){ return x < 10; }), vec.end()); for(auto&i:vec) std::cout<<i<<'\t'; return 0; }
上述代码运行后正确输出为:10 77 15
内容的提问来源于stack exchange,提问作者Zerocool_m12
相关产品推荐
相关产品推荐

