2015-11-19 4 views
-1

Я хотел бы иметь возможность удалить элемент, но я не знаю, чего мне не хватает. Программа сбой.Элементы стирания в вложенной карте

void Movies::removePeliculaAlies(short unsigned year,string title){ 
    map<string,map<unsigned short, string> >::iterator itAlies=_mapaAlies.begin(); 
    while(itAlies!=_mapaAlies.end()){ 
     map<unsigned short,string>::iterator itInterior; 
     itInterior=itAlies->second.find(year); 
     if(itInterior!=itAlies->second.end()){ 
      if(title==itInterior->second){ 
       itAlies->second.erase(itInterior);->>>>>>>>>>>>>NOT WORKING WHY? 
      } 
      if(itAlies->second.size()==0) _mapaAlies.erase(itAlies->first); 
     } 
     itAlies++; 
    } 
} 
+0

Вы говорите: «НЕ РАБОТАЕТ ПОЧЕМУ?» ... но что он делает? Он ничего не делает? Это крушение? – mkrufky

+0

Да, программа, с которой она столкнулась – user3671361

+0

Ну, может быть, вы могли бы попробовать ее отладить? – developerbmw

ответ

1

Я видел подобную проблему в своем собственном коде. Я не думаю, что авария имеет какое-то отношение к тому, что у вас есть карта внутри карты. Я думаю, что проблема скорее связана с тем фактом, что вы удаляете элемент карты во время итерации по одной и той же карте.

Я решил эту проблему в своем собственном коде следующим образом: я перебираю по карте, и если я стираю любые элементы карты, я подниму логический флаг и сломаю свой цикл итерации. После цикла, если этот флаг поднят, я перезапущу итерацию и повторяю, пока не будет необходимости в стирании. Вот мой код:

void serve::reclaim_server_resources() 
{ 
    dPrintf("()"); 

    bool erased = false; 

    for (std::map<int, serve_client>::iterator iter = client_map.begin(); 
     iter != client_map.end(); ++iter) { 
     if (!iter->second.check()) { 
      dPrintf("erasing idle client..."); 
      client_map.erase(iter->first); 
      /* stop the loop if we erased any targets */ 
      erased = true; 
      break; 
     } 
    } 

    /* if we erased a target, restart the above by re-calling this function recursively */ 
    if (erased) 
     reclaim_server_resources(); 
} 

Если удалить break; из моего цикла, код аварии, вероятно, таким же образом, что ваши делают.

Это действительно просто предложение об обходном пути к вашей проблеме. Возможно, могут быть лучшие доступные решения, но должно быть полезно, по крайней мере, знать, как подобные проблемы могут проявляться в других подобных ситуациях.

Если вы хотите попробовать свое обходное решение самостоятельно, вам может потребоваться разбить вашу функцию на две более мелкие функции, так что, когда вы перезапустите итерацию путем рекурсивного вызова новой функции, она может перезапустить итерацию внутренней карты, что перезапуск всей внешней карты.

2

Катастрофы может быть вызван этим кодом:

if(itAlies->second.size()==0) _mapaAlies.erase(itAlies->first); 
} 
itAlies++; 

В здесь вы редактируете _mapaAlies и сразу после того, что вы делаете itAlies++; даже если итератор itAlies был аннулирован редактированием.

Вместо этого вы можете попробовать первый делает приращение, а затем удаление элемента

if(itAlies->second.size()==0){ 
     map<string,map<unsigned short, string> >::iterator oldIter = itAlies; // copy the iterator 
     ++itAlies;     // increment the iterator 
     _mapaAlies.erase(oldIter); // erase the copy 
     continue;     // skip the incrementing in the end 
    } 
} 
itAlies++; 

В общем, вы должны быть варьироваться редактирования контейнера в то время как цикл через него, как редактирование может привести к аннулированию итераторы и вызвать сбои или, возможно, хуже, ,

+0

'erase' возвращает итератор сразу после стираемого элемента, поэтому вы можете сделать это, не создавая копию, просто используя' itAlies = _mapAlies.erase (itAlies); '. Вам все равно нужно «продолжить», чтобы избежать увеличения итератора во второй раз. –

+0

@ChrisDodd Согласно [cplusplus.com] (http://www.cplusplus.com/reference/map/map/erase/), новый итератор возвращается после C++ 11, который, возможно, не использовал. – Rochet2