2016-11-23 3 views
0

Je comprends que l'effacement déplace l'itérateur automatiquement, donc quand j'enlève plusieurs occurrences je dois éviter cela pour pouvoir comparer des éléments contigus. Voilà pourquoi je fais habituellement:C++ 11: Effacer plusieurs occurrences du vecteur. Quelle est la meilleure pratique?

auto i = vect.begin(); 
while (i!=vect.end()) 
    if (*i==someValue) 
     vect.erase(i); 
    else 
     ++i; 

Mais je me demandais si je pouvais aussi le faire avec une boucle, comme ceci:

for (auto i=vec.begin(); i!=vec.end(); ++i) 
    if (*i==someValue){ 
     vec.erase(i); 
     --i; 
} 

La partie -I semble un peu bizarre mais ça fonctionne . Serait-ce une mauvaise pratique? Mauvais code? Être sujet aux erreurs? Ou est-ce juste d'utiliser l'une ou l'autre option?

Merci.

+1

Assurez-vous qu'ils ne sont pas fiables. Faites ceci: https://stackoverflow.com/questions/3938838/erasing-from-a-stdvector-while-doing-a-for-each – Ryan

+0

Pourquoi sont-ils peu fiables? Je préfère m'en tenir à mon option si c'est correct. Cependant, je ne sais pas pourquoi cela ne serait pas correct (autre que la nécessité d'assigner 'i = vect.erase (i)' pour empêcher l'invalidation de l'itérateur.) –

Répondre

4

Utilisez l'option Supprimer et Effacer langage:

auto new_end = std::remove(v.begin(), v.end(), some_value); 
v.erase(new_end, v.end()); 

Ce code ci-dessus a la complexité de O (n) et il peut être exécuté en parallèle s'il pas de course de sommes données de 17 C++ avec

template< class ExecutionPolicy, class ForwardIt, class T > 
ForwardIt remove(ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, const T& value); 

ou parallelism TS

Votre code a un problème parce que de vector.modifiers#3

Effets: Invalide itérateurs et références à ou après le point de l'effacement

La norme dit que iterator est invalidée


Cependant, en réalité, la plupart des implémentations garder la point itérateur à l'ancien nœud, qui est maintenant le end si c'était le dernier élément ou l'élément suivant, alors votre code a la complexité de O (n) parce qu'il va boucler n fois et prendre n plus pour déplacer les données. Il ne peut pas non plus être exécuté en parallèle.

+0

Est-ce que mon code est incorrect pour une raison quelconque? –

+0

@VanessaLarralde Il est faux selon le libellé de la norme – Danh

+0

@Danh Non seulement par un libellé standard Comme le stockage vectoriel est garanti contigu, les itérateurs sont souvent implémentés comme de simples pointeurs de mémoire pour le stockage vectoriel. réaffecté), tous les itérateurs existants se transformeront en simples pointeurs pendants – Dmitry