17370845950

c++ vector删除元素方法_c++ vector erase用法
c++kquote>vector::erase是唯一能真正释放已删元素内存位置的函数,但不自动缩容;删除单个元素需传入合法迭代器,删除区间用两个迭代器;循环中应使用erase-remove惯用法避免迭代器失效。

vector::erase 删除单个或连续元素

erasevector 唯一能真正释放内存中已删除元素位置的成员函数,但它不自动缩容——删完后 capacity() 不变,只有 size() 减少。

删除单个元素用迭代器:

std::vector v = {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::vector v = {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

erasev.capacity() 不变,哪怕删光了所有元素,内存还在。如果确定后续不再增容,且在意内存占用,得主动调用:

v.erase(v.begin(), v.end());
v.shrink_to_fit(); // C++11 起支持,请求系统回收多余容量
  • shrink_to_fit 是“请求”,不是强制;实现可忽略(比如 libstdc++ 通常响应,MSVC 早期版本可能不)
  • 频繁调用影响性能,只在明确需要时用,例如函数返回前、长期驻留容器清理后
  • 没有等价的“清空并缩容”一键函数,clear() 只改 size,不缩容

真正难处理的是嵌套循环里删多个位置、或删除依据是运行时计算结果的情况——这时候别硬套 erase,先收集待删索引再倒序删,或者换用其他容器如 list(但要权衡随机访问代价)。