2012-01-11 141 views
1

此方法会导致中止错误:"map/set iterator not incrementable." 由于在if发生故障并且应该擦除的vaild迭代器被确定(和是)之后,经由++_iter继续在地图中的下一个迭代器失败,因为_iter不再是有效的对象/指针。C++:从地图擦除迭代器,然后递增到下一个迭代器

什么是通过地图迭代,并具有在整个删除个别项目的能力,正确的程序?

typedef std::map<std::string, BITMAP*> MapStrBmp; 
typedef MapStrBmp::iterator MapStrBmpIter; 
\\... 
void BitmapCache::CleanCache() { 
    //Clean the cache of any NULL bitmaps that were deleted by caller. 
    for(MapStrBmpIter _iter = _cache.begin(); _iter != _cache.end(); ++_iter) { 
     if(_iter->second != NULL) { 
      if((_iter->second->w < 0 && _iter->second->h < 0) == false) continue; 
     } 
     _cache.erase(_iter); 
    } 
} 
+0

@jrok:不适用于'std :: map',因为它的'value_type'是不可复制的。 – ybungalobill 2012-01-11 22:17:40

+0

我@ybungalobill去医治我的脚现在孔... – jrok 2012-01-11 22:19:20

+0

,更根本的,因为地图的元素,没有形成一个序列。 – 2012-01-11 22:20:06

回答

5

你一定要小心了:

void BitmapCache::CleanCache() { 
    //Clean the cache of any NULL bitmaps that were deleted by caller. 
    for(MapStrBmpIter _iter = _cache.begin(); _iter != _cache.end();) { 
     if(_iter->second != NULL) { 
      if((_iter->second->w < 0 && _iter->second->h < 0) == false) 
      { 
       ++_iter; 
       continue; 
      } 
     } 

     _cache.erase(_iter++); 
    } 
} 
+0

你介意用言语解释你做,请更改,所以我们没有发挥“点差”? – 2012-01-11 22:29:04

+0

为什么在擦除命令中内联的迭代器递增不同于在下一个for循环中递增?只是好奇... – v01pe 2012-01-11 23:14:56

+0

@ v01pe:在* erase调用使其无效之前,它增加了*。 – 2012-01-12 00:58:04

1

标准擦除循环的关联容器:

for (auto it = m.cbegin(); it != m.cend() /* not hoisted */; /* no increment */) 
{ 
    if (delete_condition) 
    { 
     m.erase(it++); 
    } 
    else 
    { 
     ++it; 
    } 
} 
0

的正规途径的迭代过程中安全地删除迭代器是使用container::erase结果:

void BitmapCache::CleanCache() { 
    //Clean the cache of any NULL bitmaps that were deleted by caller. 
    MapStrBmpIter _iter = _cache.begin(); 
    while (_iter != _cache.end()) { 
     bool erase_entry= true; 
     if(_iter->second != NULL) { 
      if((_iter->second->w < 0 && _iter->second->h < 0) == false) 
       erase_entry= false; 
     } 

     if (erase_entry) 
      _iter= _cache.erase(_iter); 
     else 
      ++_iter; 
    } 
} 
2

map::erase(iterator)给你消色后在地图上的迭代器指向下一个元素(如果有的话)。因此,你可以这样做:

for(MapStrBmpIter _iter = _cache.begin(); _iter != _cache.end();) { 
    if(_iter->second != NULL) { 
     if((_iter->second->w < 0 && _iter->second->h < 0) == false) { 
      ++_iter; 
      continue; 
     } 
    } 
    _iter = _cache.erase(_iter); 
} 
+1

不幸的是,它只是自C++ 11以来。 C++ 03版本返回'void'。 – ybungalobill 2012-01-11 22:24:24

+0

我认为这在C++ 11中甚至不是有效的。 C++ 11中用于擦除的函数原型看起来像这样:“迭代器擦除(const_iterator pos)'。 – gibraltar 2015-07-02 16:15:22