vector中使用erase操作删除迭代器的问题(避免野指针)以及end的地址变化

在vector中,使用erase来剔除对应的元素,但是使用iterator的时候需要注意不要让iterator变成野指针


vector的erase

在C++ Reference 中,对erase的说明如下:
vector::erase - C++ Reference http://www.cplusplus.com/reference/vector/vector/erase/

//c++98
iterator erase (iterator position);
iterator erase (iterator first, iterator last);

//c++11
iterator erase (const_iterator position);
iterator erase (const_iterator first, const_iterator last);

Erase elements
Removes from the vector either a single element (position) or a range of elements ([first,last)).
This effectively reduces the container size by the number of elements removed, which are destroyed.


可以看到erase方法可以删除vector中的一个元素,或者删除一个范围

参数说明:
position: 在vector中删除的元素的位置
first, last: 在vector中的范围[first, last),即 >= first, < last

demo

// erasing from vector
#include <iostream>
#include <vector>
using namespace std;

int main ()
{
   
   
  vector<int> myvector;

  // set some values (from 1 to 10)
  for (int i=1; i<=10; i++){
   
   
  	myvector.push_back(i);
  }

  // erase the 6th element
  myvector.erase (myvector.begin()+5);

  // erase the first 3 elements:
  myvector.erase (myvector.begin(),myvector.begin()+3);

  cout << "myvector contains:";
  for (<
<think>我们正在讨论如何避免vector迭代器失效导致的崩溃。根据引用内容,迭代器失效主要发生在以下操作后: 1. 引起底层空间改变的操作(如插入、扩容、删除等) 2. 删除操作erase) 解决方案: 1. 在修改操作后重新获取迭代器 2. 谨慎处理循环中的删除操作 3. 使用返回值更新迭代器erase会返回新的有效迭代器) 4. 避免保存end()迭代器 具体方法: 1. 插入/删除后重新赋值迭代器 2. 使用erase的返回值更新迭代器 3. 避免在循环中使用可能失效的迭代器 代码示例: ```cpp #include <vector> #include <iostream> using namespace std; int main() { vector<int> v = {1, 2, 3, 4}; // 正确删除所有元素使用erase返回值) auto it = v.begin(); while (it != v.end()) { it = v.erase(it); // erase返回下一个有效迭代器 } // 插入后重新获取迭代器 v = {1, 2, 3}; it = v.begin(); v.insert(it, 0); // 插入后it失效,需要重新获取 it = v.begin(); // 重新赋值 // 避免保存end迭代器(因为插入可能导致end失效) // 错误示例:在插入后使用旧的end迭代器 vector<int>::iterator end = v.end(); v.push_back(5); // 可能导致扩容,end失效 // 此时使用end是危险的 // 正确做法:每次需要end时都调用v.end() for (auto it2 = v.begin(); it2 != v.end(); /* 不在这里递增 */) { // 做一些操作... ++it2; // 安全递增 } return 0; } ``` 关键点总结: - 任何可能修改vector容量的操作(如push_back、insert、resize等)都会使所有迭代器失效(包括begin和end)[^1][^2] - erase操作会使被删除元素及其之后的迭代器失效,但erase会返回下一个有效的迭代器[^3] - 在循环中删除元素时,应使用erase的返回值更新迭代器,而不是手动递增[^3] - 避免在修改操作之间保存迭代器(特别是end迭代器),应每次重新获取[^4] §§相关问题§§ 1. 如何检测迭代器是否失效? 2. 在C++中,除了vector,还有哪些容器存在迭代器失效问题? 3. 使用智能指针能否避免迭代器失效问题? 4. 如何设计代码结构来最小化迭代器失效的影响?</think>### 如何避免 C++ vector 迭代器失效导致的崩溃 #### 一、迭代器失效的根本原因 当 vector 的底层存储空间发生改变时,原有迭代器指向无效内存区域,导致访问崩溃: 1. **扩容操作**:`push_back`/`insert` 导致重新分配内存,所有迭代器失效[^1][^2] ```cpp vector<int> v{1,2,3}; auto it = v.begin(); v.push_back(4); // 可能扩容 → it失效! cout << *it; // 崩溃风险 ``` 2. **删除操作**:`erase` 使被删元素之后的迭代器失效[^3] ```cpp auto it = v.begin() + 1; v.erase(v.begin()); // 删除元素 cout << *it; // 原第二个元素现在位置已变! ``` 3. **修改操作**:`resize`/`assign` 等改变容量的操作[^4] --- #### 二、避免崩溃的实践方法 ##### 1. 修改后立即更新迭代器 ```cpp vector<int> v = {1, 2, 3}; auto it = v.begin(); // 插入后重新获取迭代器 v.insert(it, 0); it = v.begin(); // 关键:更新迭代器 // 删除使用返回值更新 it = v.erase(it); // 返回下一个有效迭代器 ``` ##### 2. 循环中安全删除元素 ```cpp for (auto it = v.begin(); it != v.end(); /* 不在此处递增 */) { if (*it % 2 == 0) { it = v.erase(it); // 用返回值更新迭代器 } else { ++it; // 安全时才递增 } } ``` ##### 3. 避免保存长期迭代器 ```cpp // 危险:保存end迭代器 auto end_it = v.end(); v.push_back(10); // 可能导致end_it失效 // 正确:每次实时获取 for (auto it = v.begin(); it != v.end(); ++it) { // 安全操作 } ``` ##### 4. 使用索引替代迭代器(简单场景) ```cpp for (size_t i = 0; i < v.size(); ++i) { // 索引不受迭代器失效影响 if (v[i] == target) { v.erase(v.begin() + i); --i; // 调整索引位置 } } ``` ##### 5. 预分配空间避免扩容 ```cpp vector<int> v; v.reserve(100); // 预分配足够空间 for (int i = 0; i < 100; ++i) { v.push_back(i); // 不会触发扩容 // 迭代器保持有效 } ``` --- #### 三、调试与检测工具 1. **启用迭代器调试**(GCC): ```bash g++ -D_GLIBCXX_DEBUG -o program source.cpp ``` 运行时自动检测失效迭代器并抛出异常[^2] 2. **AddressSanitizer**: ```bash g++ -fsanitize=address -g source.cpp ``` 检测指针访问(包括失效迭代器) --- #### 四、关键总结表 | **操作** | **失效范围** | **安全处理方式** | |------------------|----------------------|-------------------------------| | `push_back` | 所有迭代器可能失效 | 操作后重新获取迭代器 | | `insert` | 插入点之后迭代器失效 | 使用返回值更新迭代器 | | `erase` | 被删元素之后失效 | `it = erase(it)` | | `resize/reserve` | 所有迭代器失效 | 操作完成后重新获取 | | `clear` | 所有迭代器失效 | 重新初始化迭代器 | > 黄金法则:**任何修改 vector 容量的操作后,都假设所有现有迭代器已失效**。 ---
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值