Map erase的两种方法

本文介绍了两种在C++中遍历并删除std::map容器元素的方法。方法一使用map的erase方法返回的新迭代器更新当前迭代器;方法二利用迭代器后增的特点,在erase前先进行后增操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方法一:

[cpp]  view plain copy
  1. std::map<std::string, std::string > mapTest;  
  2. bool TestVal(const std::string & val);  
  3.   
  4. ......  
  5. std::map<std::string, std::string >::iterator it = mapTest.begin();  
  6. while(it != mapTest.end())  
  7. {  
  8.          if(TestVal(it->second))  
  9.          {  
  10.                  it = mapTest.erase(it);  
  11.          }  
  12.          else  
  13.                  it++;  
  14. }  
  15. ...........  
在这种方式中,通过std::map的erase方法在释放了it后会返回指向下一个元素的指针来获取最新的iterator


方法二:

[cpp]  view plain copy
  1. std::map<std::string, std::string > mapTest;  
  2. bool TestVal(const std::string & val);  
  3.   
  4. ......  
  5. std::map<std::string, std::string >::iterator it = mapTest.begin();  
  6. while(it != mapTest.end())  
  7. {  
  8.          if(TestVal(it->second))  
  9.          {  
  10.                 mapTest.erase(it++);  
  11.          }  
  12.          else  
  13.                  it++;  
  14. }  
  15. ...........  
该方法中利用了后++的特点,这个时候执行mapTest.erase(it++);这条语句分为三个过程

1、先把it的值赋值给一个临时变量做为传递给erase的参数变量

2、因为参数处理优先于函数调用,所以接下来执行了it++操作,也就是it现在已经指向了下一个地址。

3、再调用erase函数,释放掉第一步中保存的要删除的it的值的临时变量所指的位置。


如果只是mapTest.erase(it); 当这条语句执行完后,it就是一个非法指针,如果再执行++就会出错


总结,对于iter的移动在对erase时需要注意。

### C++ 中 `map` 的 `erase` 函数使用方法C++ 标准库中,`std::map` 提供了多种方式用于删除其中存储的键值对。以下是关于 `std::map` 和其成员函数 `erase` 的详细介绍以及一些常见用法。 #### 1. `erase` 方法简介 `std::map` 的 `erase` 成员函数支持三种不同的签名形式[^1]: - **通过指定键名删除单个元素** ```cpp void erase(const key_type& k); ``` 此版本接受一个键作为参数并移除对应的键值对。如果该键不存在,则不会有任何影响。 - **通过迭代器删除单个元素** ```cpp iterator erase(const_iterator position); ``` 这种方式允许传入指向某个特定位置的迭代器来删除对应节点。返回的是下一个有效迭代器的位置。 - **通过范围删除多个连续元素** ```cpp iterator erase(const_iterator first, const_iterator last); ``` 可以一次性清除由两个边界所界定的一组相邻项目;注意这里不包括最后一个迭代器指向的那个条目本身。 #### 2. 示例代码展示不同类型的删除操作 下面给出几个具体的例子说明上述每一种情况下的实际应用情形: ##### (1)基于关键字删除单一记录实例演示 ```cpp #include <iostream> #include <map> int main(){ std::map<int,std::string> myMap; // 添加几项测试数据 myMap[1]="one"; myMap[2]="two"; myMap[3]="three"; // 打印原始内容 for(auto &p :myMap){ std::cout<< p.first <<":"<<p.second<<"\n"; } // 移除key为2的数据项 myMap.erase(2); std::cout<<"After erasing:\n"; for(auto &p :myMap){ std::cout<< p.first <<":"<<p.second<<"\n"; } } ``` ##### (2)利用迭代器定位目标后执行单项剔除动作示范程序片段 ```cpp auto iter=myMap.find(1); if(iter!=myMap.end()){ myMap.erase(iter); } ``` ##### (3)采用区间模式批量清理选定部分区域内的全部资料范例脚本 ```cpp // 清理从第一个到倒数第二个之间的所有元素 myMap.erase(myMap.begin(), --myMap.end()); ``` 需要注意,在循环过程中调用容器内部修改结构的操作(比如插入或者删除),可能会使现有的迭代器失效。因此对于有序关联型容器而言,建议先收集待处理对象列表再统一处置它们,而不是直接在线程体内即时销毁当前访问单元[^2]。 #### 3. 特殊注意事项 当涉及到自定义比较规则时(例如 reverse order 或者其他复杂逻辑),应格外小心避免因不当操作引发未定义行为或异常终止等问题发生。例如前面提到的例子就是因为试图在同一轮次内既读取又改变集合状态而导致错误的结果[^2]。 为了安全起见,可以考虑如下改进方案之一: - 将要被删掉的对象存放到临时数组里稍后再逐一实施消除; - 利用高级算法如 remove_if 结合 lambda 表达式完成筛选工作然后再整体裁剪剩余空间大小至合适程度即可达到目的而无需担心中途破坏原有秩序关系造成混乱局面出现。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值