Home >Backend Development >C++ >How to Safely Remove Elements from a `std::vector` While Iterating?
Iterating and Erasing from std::vector
The recommended approach for iterating through a std::vector is to use iterators. However, erasing elements while iterating can invalidate the iterator.
To address this issue, it's crucial to modify the iterator assignment after erasing an element, as demonstrated below:
<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>
It's important to note that the end of the container should be recalculated each time after erasing an element.
A more efficient alternative is to combine std::remove_if and erase():
<code class="cpp">iterator it = std::remove_if(begin, end, pred); vec.erase(it, vec.end());</code>
This approach changes the time complexity from O(N^2) to O(N). Here's an example of a predicate for removing elements:
<code class="cpp">struct predicate { bool operator()(const T& pX) const { return pX.shouldIBeRemoved(); } };</code>
For your specific case, you can use a more generic approach:
<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>
Using this approach:
<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>
Furthermore, lambda expressions can simplify this process, as supported in both Boost and C 11.
The above is the detailed content of How to Safely Remove Elements from a `std::vector` While Iterating?. For more information, please follow other related articles on the PHP Chinese website!