Itération et effacement de std::vector
L'approche recommandée pour itérer dans un std::vector consiste à utiliser des itérateurs. Cependant, effacer des éléments lors d'une itération peut invalider l'itérateur.
Pour résoudre ce problème, il est crucial de modifier l'affectation de l'itérateur après avoir effacé un élément, comme démontré ci-dessous :
<code class="cpp">for (iterator it = begin; it != end(container) /* !!! */; ) { if (it->somecondition()) { it = vec.erase(it); // Returns the new iterator to continue from. } else { ++it; } }</code>
Il est important de notez que la fin du conteneur doit être recalculée à chaque fois après avoir effacé un élément.
Une alternative plus efficace consiste à combiner std::remove_if et Eraser():
<code class="cpp">iterator it = std::remove_if(begin, end, pred); vec.erase(it, vec.end());</code>
Cette approche change la complexité temporelle de O(N^2) à O(N). Voici un exemple de prédicat pour supprimer des éléments :
<code class="cpp">struct predicate { bool operator()(const T& pX) const { return pX.shouldIBeRemoved(); } };</code>
Pour votre cas spécifique, vous pouvez utiliser une approche plus générique :
<code class="cpp">class remove_by_caller { public: remove_by_caller(AguiWidgetBase* pWidget) : mWidget(pWidget) {} template <typename T> bool operator()(const T& pX) const { return pX.getCaller() == mWidget; } private: AguiWidgetBase* mWidget; };</code>
Utiliser cette approche :
<code class="cpp">std::vector<AguiTimedEvent>::iterator it = std::remove_if(timedEvents.begin(), timedEvents.end(), remove_by_caller(widget)); timedEvents.erase(it, timedEvents.end());</code>
De plus, les expressions lambda peuvent simplifier ce processus, comme pris en charge à la fois par Boost et C 11.
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!