应使用erase–remove惯用法删除vector中所有匹配值:vec.erase(remove(vec.begin(), vec.end(), val), vec.end()),或对复杂条件用remove_if配合lambda;手写循环需反向遍历或迭代器重赋值以避免失效问题。

直接用 erase 配合 find 只能删第一个匹配项
很多人试过 vec.erase(find(vec.begin(), vec.end(), val)),确实能删,但只删最前面那个。如果 vector 里有多个 val,后续的全留着——这不是“根据值删除元素”的本意。
真正要删所有匹配值,得用迭代器遍历 + 条件擦除,或者更稳妥的「erase–remove 惯用法」。
erase–remove 惯用法是标准且安全的做法
这是 C++ 标准库推荐的方式,不依赖手写循环,也不容易搞错迭代器失效问题。
-
remove不真删元素,而是把所有不等于val的元素往前挪,返回新逻辑结尾的迭代器 -
erase接收这个迭代器区间,一次性删掉后面“废弃”部分 - 两步合起来:
vec.erase(remove(vec.begin(), vec.end(), val), vec.end()) - 注意:必须包含
<algorithm></algorithm>头文件
要删满足复杂条件的元素?改用 remove_if
比如删所有偶数、删长度小于 3 的字符串、删指针为空的对象……这时 remove 不够用,得上 remove_if。
- 传一个可调用对象(lambda、函数指针或函数对象)作为判断逻辑
- 示例(删所有负数):
vec.erase(remove_if(vec.begin(), vec.end(), [](int x) { return x - lambda 捕获要注意:若需访问外部变量,确保生命周期足够长,别捕获局部地址后还去 erase
- 对自定义类型,确保谓词不抛异常,否则
erase–remove的强异常安全不成立
手写循环删除时,反向遍历 or 迭代器重赋值是关键
如果非要用 for 或 while 遍历删除,正向 + erase 极易出错:一次 erase 后当前迭代器失效,且后续元素前移,跳过下一个。
- 安全做法一(反向):
for (int i = vec.size() - 1; i >= 0; --i) if (vec[i] == val) vec.erase(vec.begin() + i); - 安全做法二(迭代器重置):
for (auto it = vec.begin(); it != vec.end(); ) if (*it == val) it = vec.erase(it); else ++it; - 前者适合索引访问快的场景(
vector没问题),后者通用但每次erase有移动开销 - 千万别写
it++后再erase(it)—— 这会删错位置,甚至崩溃
实际项目里,只要不是特殊调试场景,优先用 erase–remove;涉及多字段判断或运行时条件时,remove_if + lambda 更灵活;手写循环只在需要中间状态处理(比如记录删了几个、触发回调)时才考虑,而且必须小心迭代器管理。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











