C++: стирание итератора с карты с последующим увеличением до следующего итератора
Этот метод вызывает ошибку прерывания: "map/set iterator not incrementable."
В связи с этим после if
происходит сбой и определяется пустой итератор, который должен быть удален, (и есть), переход к следующему итератору на карте через ++_iter
не удается, потому что _iter
больше не является допустимым объектом / указателем.
Какова правильная процедура для итерации по карте И с возможностью удаления отдельных элементов повсюду?
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);
}
}
4 ответа
Вы просто должны быть немного осторожнее:
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++);
}
}
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);
}
Стандартный цикл стирания для ассоциативного контейнера:
for (auto it = m.cbegin(); it != m.cend() /* not hoisted */; /* no increment */)
{
if (delete_condition)
{
m.erase(it++);
}
else
{
++it;
}
}
Канонический способ безопасного удаления итераторов во время итерации заключается в использовании результата 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;
}
}