2015-11-19 7 views
-1

J'aimerais pouvoir supprimer un élément mais je ne sais pas ce qui me manque. Le programme se bloque.Effacer des éléments dans une carte imbriquée

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

Vous dites: «PAS DE TRAVAIL POURQUOI? ... mais que fait-il? Est-ce que ça ne fait rien? Est-ce que ça plante? – mkrufky

+0

Oui le programme plantage – user3671361

+0

Eh bien peut-être que vous pourriez essayer de le déboguer? – developerbmw

Répondre

1

J'ai rencontré un problème similaire dans mon propre code. Je ne pense pas que le crash ait quelque chose à voir avec le fait que vous avez une carte dans une carte. Je pense que le problème est plus vraisemblablement lié au fait que vous supprimez un élément de la carte tout en itérant sur la même carte. J'ai résolu ce problème dans mon propre code de la façon suivante: Je répète sur la carte, et si j'efface des éléments de la carte, je lève un drapeau booléen et romps ma boucle d'itération. Après la boucle, si ce drapeau est levé, je vais recommencer l'itération et répéter jusqu'à ce qu'il n'y ait plus d'effacements nécessaires. Voici mon code:

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(); 
} 

Si je retire la break; de ma boucle, les accidents de code, probablement de la même manière que le vôtre.

Ceci est vraiment juste une suggestion pour une solution à votre problème. Peut-être y aurait-il de meilleures solutions disponibles, mais il devrait être utile, au moins, de savoir comment des problèmes similaires peuvent se manifester dans d'autres situations similaires. Si vous voulez essayer ma solution de contournement vous-même, vous pouvez décomposer votre fonction en deux fonctions plus petites, de sorte que lorsque vous redémarrerez l'itération en appelant récursivement la nouvelle fonction, elle peut redémarrer l'itération de la carte interne plutôt que redémarrer l'ensemble de la carte externe.

2

L'accident peut être causé par ce code:

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

Ici vous modifiez _mapaAlies et juste après que vous ne itAlies++; même si l'itérateur itAlies a été invalidée par la modification.

vous pourriez plutôt essayer d'abord faire l'incrément, puis supprimer l'élément

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++; 

En général, vous devriez être varier d'édition d'un conteneur en boucle à travers elle que l'édition peut invalider les itérateurs et causer des accidents ou peut-être pire .

+0

'erase' renvoie un itérateur juste après l'élément effacé, donc vous pouvez le faire sans créer de copie en utilisant simplement' itAlies = _mapAlies.erase (itAlies); '. Vous avez toujours besoin de 'continuer; 'pour éviter d'incrémenter l'itérateur une seconde fois. –

+0

@ChrisDodd Selon [cplusplus.com] (http://www.cplusplus.com/reference/map/map/erase/), le nouvel itérateur est retourné après C++ 11 que le demandeur ne pourrait pas utiliser. – Rochet2