2012-01-11 28 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: 'value_type'はコピー不可能なので、' std :: map'には適用されません。 – ybungalobill

+0

@ybungalobill足の中の私の穴を治すつもりです... – jrok

+0

以上は基本的にマップの要素がシーケンスを構成しないためです。 –

答えて

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

あなたが行った変更を単語で説明してもらえますか?「相違点を発見」する必要はありませんか? –

+0

eraseコマンドのイテレータのインラインをインクリメントして、次のforループでインクリメントするのと違うのはなぜですか?ちょうど興味があります... – v01pe

+0

@ v01pe: 'erase'の呼び出しが無効になる前にインクリメントされています。 –

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

+0

これはC++ 11でも有効ではないと思います。 C++ 11での消去の関数プロトタイプは、この 'iterator erase(const_iterator pos)'のように見えます。 – gibraltar

関連する問題