2015-07-23 8 views
-1

Я пытаюсь стереть некоторые элементы с std :: map, все кажется, что работает правильно, до сегодняшнего дня, когда я обнаруживаю, что запускает бесконечный цикл.ошибка при попытке удалить элемент из std :: map в C++

double PMinThreshold = 0.05; 
typedef std::map<int, double>::iterator predsIterator; 
std::map<int, double> preds; 

// Initialize preds under some conditions; otherwise, let the map empty 

for (predsIterator it=preds.begin();it!=preds.end();it++){ 
     it->second = it->second * mult; 


     if (it->second < PMinThreshold){ 
      it2 = it; 
      it++; 
      preds.erase(it2); 
     } 
} 

ПРИМЕЧАНИЕ: i'am получает ошибку, когда Preds пусто, я не знаю, если карта была ранее пустой перед входом в цикле (который, кажется мне невозможным, чтобы вызвать бесконечный цикл) или стирание операция делает его пустым.

Спасибо,

+1

'Я не знаю, была ли карта ранее пуста' ... Как насчет использования отладчика, чтобы узнать? – user2079303

+0

Пожалуйста, отправьте код, который можно скомпилировать, и позволит читателю локально воспроизвести проблему. (т. е.: включить необходимые, основные и т. д.) – dingalapadum

+0

Возможный дубликат [Что произойдет, если вы вызовеете erase() на элементе карты при повторении от начала до конца?] (http://stackoverflow.com/questions/263945/what-happens-if-you-call-erase-on-a-map-element-while-iterating-from-begin-to –

ответ

2
double PMinThreshold = 0.05; 
std::map<int, double>::iterator it = preds.begin(); 
std::map<int, double> preds; 

// Initialize preds under some conditions; otherwise, let the map empty 
for (;it!=preds.end();) 
{ 
    it->second = it->second * mult; 
    if (it->second < PMinThreshold) 
    {   
    preds.erase(it++); 
    }else 
    ++it; 
} 
2

Вы должны использовать алгоритм, как станд :: remove_if вместо этого for цикла с if заявления внутри

[Edit]

Поскольку remove_if не работает ассоциативный контейнер как @ Ari0nhh указал, что вы можете использовать комбинацию std::find_if и erase, как объяснено в this SO answer.

+0

'remove_if' не работает для ассоциативных контейнеров, таких как std :: map – Ari0nhh

2

, когда if условие условия true, указатель итератора карты в неправильном положении, указатель итератора перемещается два раза. Это может быть работа, как показано ниже:

for (predsIterator it = preds.begin(); it != preds.end();) { 
    it->second = it->second * mult; 

    if (it->second < PMinThreshold) { 
     it = preds.erase(it); 
    } else { 
     ++it; 
    } 
} 
+0

' it = preds.erase (it); 'не будет работать. См.: Возвращаемое значение: http://www.cplusplus.com/reference/map/map/erase/. erase не возвращает итератор. Возможно, тестирование перед публикацией поможет. – dingalapadum

+1

@dingalapadum Вы должны посмотреть на 'erase' C++ 11. –

+0

@ JonathanMee Достаточно честно ... Я не видел, чтобы C++ 11 упоминался где-нибудь ... может быть, потому что это не (в тегах, в вопросе или в ответе) ........ ..... можно было бы где-то упомянуть. Но спасибо, что разместили ссылку на соответствующую документацию: http://en.cppreference.com/w/cpp/container/map/erase – dingalapadum

Смежные вопросы