Effacer des éléments d'un std :: vecteur lors d'une itération avec une boucle For basée sur une plage
Itérer sur un std :: vecteur et supprimer les éléments correspondant à une certaine condition peuvent être une tâche courante en programmation. Cependant, la syntaxe standard de la boucle For basée sur une plage présente un défi, car tenter d'effacer un élément lors d'une itération peut invalider l'itérateur.
Le problème de l'effacement dans une boucle For basée sur une plage
L'extrait de code suivant illustre le problème :
for(iterator it = begin; it != end; ++it) { if(it->somecondition() ) { erase it } }
Bien que l'intention soit de supprimer les éléments répondant à la condition, cette approche est incorrecte. Lorsqu'un élément est effacé, l'itérateur devient invalide. Continuer à itérer avec cet itérateur conduit à un comportement indéfini.
Solution 1 : Utiliser une boucle For régulière avec manipulation explicite de l'itérateur
Une solution consiste à utiliser une boucle for régulière avec manipulation explicite de l'itérateur :
for(iterator it = begin; it != end(container) /* !!! */;) { if (it->somecondition()) { it = vec.erase(it); // Returns the new iterator to continue from. } else { ++it; } }
Notez ici la différence cruciale : nous appelons explicitement end(container) à chaque itération pour obtenir un nouvel itérateur de fin. Ceci est nécessaire car l'effacement d'un élément invalide l'itérateur d'origine.
Solution 2 : Utiliser std::remove_if et effacer
Une alternative plus efficace consiste à combiner std:: Remove_if et Eraser():
iterator it = std::remove_if(begin, end, pred); vec.erase(it, vec.end());
std::remove_if supprime les éléments correspondant à un prédicat spécifié, tandis que Eraser() les supprime. Cette approche réduit la complexité temporelle de O(N) à partir de O(N2) dans la première solution.
Solution spécifique à l'exemple fourni
Dans l'exemple spécifique donné, le code suivant peut être utilisé pour supprimer les événements chronométrés associés à un widget particulier :
class remove_by_caller { public: remove_by_caller(AguiWidgetBase* pWidget) : mWidget(pWidget) {} template <typename T> // for now a template bool operator()(const T& pX) const { return pX.getCaller() == mWidget; } private: AguiWidgetBase* mWidget; }; std::vector<AguiTimedEvent>::iterator it = std::remove_if(timedEvents.begin(), timedEvents.end(), remove_by_caller(widget)); timedEvents.erase(it, timedEvents.end());
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!