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

本文详细介绍了在C++中使用STL map容器时,如何安全地在迭代过程中删除元素的两种方法。第一种方法利用了map的erase方法特性,它在删除元素后会返回指向下一个元素的迭代器。第二种方法则巧妙运用了后置++运算符的特性,确保在删除当前元素后迭代器能正确指向下一个元素,避免了悬挂指针的问题。

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

转载地址:https://blog.youkuaiyun.com/bizer_csdn/article/details/53160666

方法一:

[cpp] view plaincopy

  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 plaincopy

  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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值