std::map::erase的用法及陷阱

本文介绍了两种在C++中遍历并删除std::map容器内元素的方法。第一种方法利用了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时需要注意。

void CameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove) { 1. lock_acquire: 调用 Autolock 将获取锁 this->mInflightLock.mMutex。[显示详情] 1107 Mutex::Autolock _l(mInflightLock); 2. 对 cachesToRemove 的另一元素迭代。 5. 对 cachesToRemove 的另一元素迭代。 1108 for (auto& cache : cachesToRemove) { 1109 auto cbsIt = mCirculatingBuffers.find(cache.streamId); 3. 条件 cbsIt == std::__1::map<int, std::__1::unordered_map<unsigned long long, native_handle const *, std::__1::hash<unsigned long long>, std::__1::equal_to<unsigned long long>, std::__1::allocator<std::__1::pair<unsigned long long const, native_handle const *> > >, std::__1::less<int>, std::__1::allocator<std::__1::pair<int const, std::__1::unordered_map<unsigned long long, native_handle const *, std::__1::hash<unsigned long long>, std::__1::equal_to<unsigned long long>, std::__1::allocator<std::__1::pair<unsigned long long const, native_handle const *> > > > > >::iterator const(this->mCirculatingBuffers.end()),使用了 true 分支。 6. 条件 cbsIt == std::__1::map<int, std::__1::unordered_map<unsigned long long, native_handle const *, std::__1::hash<unsigned long long>, std::__1::equal_to<unsigned long long>, std::__1::allocator<std::__1::pair<unsigned long long const, native_handle const *> > >, std::__1::less<int>, std::__1::allocator<std::__1::pair<int const, std::__1::unordered_map<unsigned long long, native_handle const *, std::__1::hash<unsigned long long>, std::__1::equal_to<unsigned long long>, std::__1::allocator<std::__1::pair<unsigned long long const, native_handle const *> > > > > >::iterator const(this->mCirculatingBuffers.end()),使用了 false 分支。 1110 if (cbsIt == mCirculatingBuffers.end()) { 1111 // The stream could have been removed 4. 继续循环 1112 continue; 1113 } 1114 CirculatingBuffers& cbs = cbsIt->second; 1115 auto it = cbs.find(cache.bufferId); 7. 条件 it != std::__1::unordered_map<unsigned long long, native_handle const *, std::__1::hash<unsigned long long>, std::__1::equal_to<unsigned long long>, std::__1::allocator<std::__1::pair<unsigned long long const, native_handle const *> > >::iterator const(cbs->end()),使用了 true 分支。 1116 if (it != cbs.end()) { CID 171518: (#1 of 1): 持有锁时等待 (SLEEP) 8. sleep: 对 freeBuffer 的调用可能在持有锁 this->mInflightLock.mMutex 的情况下睡眠。[显示详情] 1117 sHandleImporter.freeBuffer(it->second); 1118 cbs.erase(it); 1119 } else { 1120 ALOGE("%s: stream %d buffer %" PRIu64 " is not cached", 1121 __FUNCTION__, cache.streamId, cache.bufferId); 1122 } 1123 } 1124
最新发布
07-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值