C ++: стирание итератора с карты с последующим увеличением до следующего итератора - PullRequest
2 голосов
/ 12 января 2012

Этот метод вызывает ошибку прерывания: "map/set iterator not incrementable." Из-за этого после сбоя if и определения итератора vaild, который должен быть удален (и есть), переход к следующему итератору на карте с помощью ++_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 ]

6 голосов
/ 12 января 2012

Вы просто должны быть немного осторожнее:

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++);
    }
}
2 голосов
/ 12 января 2012

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 голос
/ 12 января 2012

Стандартный цикл стирания для ассоциативного контейнера:

for (auto it = m.cbegin(); it != m.cend() /* not hoisted */; /* no increment */)
{
    if (delete_condition)
    {
        m.erase(it++);
    }
    else
    {
        ++it;
    }
}
0 голосов
/ 12 января 2012

Канонический способ безопасного стирания итераторов во время итерации - использовать результат 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;
    }
}
...