9
votes

un petit problème avec std :: vector et changeant la collection en boucle à travers elle

Cette boucle change les itérateurs lors de l'exécution:

std::vector<int> c;
c.push_back(1);
c.push_back(2);

std::vector<int>::iterator iter    = c.begin();
std::vector<int>::iterator endIter = c.end();

while( iter != endIter )
{
    std::cout << (*iter) << std::endl;
    iter = c.erase(iter);
}


5 commentaires

Vous pouvez le faire sans itérateurs ou le faire en deux étapes: d'abord les imprimer toutes, puis effacez toute la liste. Cela dépend de ce que vous essayez de faire et une démonstration comme celle-ci n'essaie pas vraiment de faire quoi que ce soit. (Auto est complètement orthogonal à ceci: Demander cela dans une autre question.)


C'est un exemple factice. Mais ce que je stocke vraiment dans le vecteur est cvpoint2d32f * . Et dans le pendant boucle, j'ajoute les informations de ces cvpoint2d32f * pour remplir un cv_mat_elem . Mais à chaque itération, je veux supprimer l'effacement de l'élément depuis que je n'en ai plus besoin.


"Depuis que je n'en ai plus besoin" est une mauvaise raison de transformer votre code à l'envers. Passez à travers tout le vecteur et ensuite, lorsque vous avez terminé, écrivez-le puisque vous n'en avez plus besoin. Simple et lisible. En ce qui concerne la mise en cache () - En général, n'étudiez pas le compilateur.


Ok, merci pour vos explications.


Dupliqué possible de Pouvez-vous supprimer des éléments d'un std :: Liste en itération à travers elle?


4 Réponses :


12
votes

effacer un élément change fin () code>. Changer la boucle:

while( iter != c.end())


0 commentaires

22
votes

Ne pas simplement mettre en cache l'itérateur final qui sera invalidé: xxx

ou effacer le vecteur après l'impression: xxx


1 commentaires

Un autre bon idiome pour consommer un vecteur dans un contexte multi-threadé consiste à acquérir le verrou, puis swap (accumulé_vector, local_vector) puis déposez le verrou. Traitez ensuite les valeurs capturées dans local_vector et jetez-la.



7
votes

soit

  • réécrire comme p>

    while( iter != endIter )
    {
        std::cout << (*iter) << std::endl;
        iter = c.erase(iter);
        endIter = c.end();
    }
    
    • "rafraîchir" tout itérateurs potentiellement invalidés après chaque opération d'invalidation p>

      while( iter != c.end() )
      {
          std::cout << (*iter) << std::endl;
          iter = c.erase(iter);
      }
      


0 commentaires

3
votes

Une manière plus idiomatique de faire cela ...

while(c.begin() != c.end()) c.pop_back();


1 commentaires

Merci beaucoup pour l'info !