
vector::erase 删除单个或连续元素
erase 是 vector 唯一能真正释放内存中已删除元素位置的成员函数,但它不自动缩容——删完后 capacity() 不变,只有 size() 减少。
删除单个元素用迭代器:
std::vectorv = {1, 2, 3, 4, 5}; auto it = v.begin() + 2; // 指向 3 v.erase(it); // v 变为 {1, 2, 4, 5}
删除区间用两个迭代器:
v.erase(v.begin() + 1, v.begin() + 3); // 删除下标 1~2(含头不含尾),即 2 和 4 → {1, 5}
- 传入的迭代器必须合法,
v.erase(v.end())是未定义行为 - 删除后原迭代器失效,尤其注意循环中边遍历边
erase时不能直接i++ - 连续删除多个不相邻元素时,反复调用
erase效率低(每次都要移动后续元素)
循环中安全删除满足条件的元素(erase–remove 惯用法)
想删掉所有值为 3 的元素?别写 for (auto it = v.begin(); it != v.end(); ++it) 加 erase —— 迭代器失效会导致跳过元素或崩溃。
立即学习“C++免费学习笔记(深入)”;
正确做法是用 std::remove 配合 erase:
std::vectorv = {1, 3, 2, 3, 4, 3}; v.erase(std::remove(v.begin(), v.end(), 3), v.end()); // v 变为 {1, 2, 4}
-
std::remove不真删,只是把要保留的元素前移,返回新逻辑结尾的迭代器 -
erase接收该迭代器和v.end(),一次性擦除“冗余尾部” - 这是标准、高效、安全的组合,适用于所有可比较类型
- 对自定义类型,用
std::remove_if替代,传入 lambda 或谓词
按索引删除(比如删第 i 个)要小心迭代器转换
vector 没有 erase(int index) 重载,必须转成迭代器。常见错误是越界没检查:
- 错误:
v.erase(i)—— 编译不过,erase只接受迭代器 - 危险:
v.erase(v.begin() + i)—— 若i >= v.size(),结果未定义 - 安全写法:
if (i >= 0 && i < static_cast(v.size())) { v.erase(v.begin() + i); }
注意 size() 返回 size_t,与有符号 int 比较时可能隐式转换出问题,显式转成 size_t 或用 static_cast 更稳妥。
想真正释放内存?erase 后手动 shrink_to_fit
erase 后 v.capacity() 不变,哪怕删光了所有元素,内存还在。如果确定后续不再增容,且在意内存占用,得主动调用:
v.erase(v.begin(), v.end()); v.shrink_to_fit(); // C++11 起支持,请求系统回收多余容量
-
shrink_to_fit是“请求”,不是强制;实现可忽略(比如 libstdc++ 通常响应,MSVC 早期版本可能不) - 频繁调用影响性能,只在明确需要时用,例如函数返回前、长期驻留容器清理后
- 没有等价的“清空并缩容”一键函数,
clear()只改size,不缩容
真正难处理的是嵌套循环里删多个位置、或删除依据是运行时计算结果的情况——这时候别硬套 erase,先收集待删索引再倒序删,或者换用其他容器如 list(但要权衡随机访问代价)。











