map / set итератор не увеличивается, map / set итератор не увеличивается - PullRequest
12 голосов
/ 25 января 2012
Driver::~Driver()
{
    AutoCritSec acsDriverList(m_csDriverList,true);
    DRIVERLIST::iterator it = m_DriverList.begin();
    for(;it!=m_DriverList.end();it++) 
    {
        if (it->second == this) 
        {
            m_DriverList.erase(it);
            it = m_DriverList.begin();
        }
    }
}

Когда я компилирую свою программу в visual studio 2003, моя программа работает хорошо. но когда я делаю то же самое в 2010 году, то при закрытии приложения я получаю сообщение об ошибке типа

Expression:map/set iterator not incrementable

и когда я нажимаю, чтобы игнорировать это, я получаю

Expression:"standard c++ library out of range" && 0

Кто-нибудь знает, что здесь происходит: я буду чрезвычайно признателен за любые предложения от кого-либо. Тонны благодарностей и теплых пожеланий.

Ответы [ 2 ]

13 голосов
/ 25 января 2012

Если this является единственным элементом в списке, вы переполните конец списка.

После удаления this из списка вы сбрасываете it = m_DriverList.begin();. Это отлично. Затем вычисляется выражение цикла (i++ из оператора for), в результате чего it продвигается выше конца диапазона.

Продвижение итератора после конца контейнера приводит к тому, что программа демонстрирует неопределенное поведение. Последние версии Visual C ++ помогают обнаружить многие распространенные ошибки итераторов в отладочных сборках вашей программы и выдвигают утверждения, помогающие вам их решить.

Вы можете решить проблему, удалив выражение цикла и переместив его в оператор else:

while (it != m_DriverList.end())
{
    if (it->second == this)
    {
        m_DriverList.erase(it);
        it = m_DriverList.begin();
    }
    else
    {
        ++it;
    }
}

Хотя перезапуск итерации при каждом удалении элемента довольно расточителен. Вместо этого рассмотрим использование итератора, возвращаемого вызовом erase:

it = m_DriverList.erase(it);
10 голосов
/ 25 января 2012

Правильная идиома стирания для ассоциативных контейнеров выглядит следующим образом:

for (auto it = container.begin(); it != container.end() /* not hoisted */; /* no inc. */ )
{
    if (delete_condition)
    {
        container.erase(it++);
    }
    else
    {
        ++it;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...