SoFunction
Updated on 2025-05-11

Guide to avoid pitfalls when C++ iterator failure

1. What is iterator failure?

In C++, an iterator is a pointer-like object used to traverse STL containers (such as vector, list, map, etc.).

Iterator failedIt means that after performing certain operations on the container (such as insertion and deletion), the originally valid iterator becomes unavailable. Continuing to use it will cause undefined behavior (Undefined Behavior, UB), such as program crashes, data errors, etc.

2. What operations will cause the iterator to fail?

Different containers have different iterator failure rules, this article mainly discussesvectorIterator failure problem.

2.1 vector insert operation (push_back, insert)

WhenvectorWhen inserting an element:

  • ifsize() == capacity()(Capacity full)
    • vectorThe larger memory will be re-allocated and the original data will be copied.
    • All iterators fail(includebegin()end()wait).
  • ifsize() < capacity()(Capacity not full)
    • The iterator before the insertion point is still valid
    • The insertion point and subsequent iterator fail(because elements may be moved).

Example: push_back causes the iterator to fail

vector&lt;int&gt; v = {1, 2, 3};
auto it = (); // it points to 1v.push_back(4);      // Reallocation of memory may be triggeredcout &lt;&lt; *it;         // ❌ Danger!it Possible failure

How to avoid it?

  • Reserve space in advancereserve()):
vector&lt;int&gt; v;
(100);    // Reserve 100 elements of spaceauto it = ();
v.push_back(1);    // Will not be reassigned,it Still valid
  • Use index instead of iterator(if allowed).

2.2 vector deletion operation (erase, pop_back)

WhenvectorWhen deleting elements:

  • The iterator of the deleted element is invalid
  • All iterators after the deleted element are invalid(because the subsequent elements will move forward).
  • The iterator before deleting the point is still valid

Example: erase causes the iterator to fail

vector&lt;int&gt; v = {1, 2, 3, 4};
auto it = () + 2; // it points to 3(() + 1);  // Delete 2cout &lt;&lt; *it;             // ❌ Danger!it Have expired(3 Already moved forward)

How to delete correctly?

  • useeraseThe return value of(Return to the next valid iterator):
vector&lt;int&gt; v = {1, 2, 3, 4};
auto it = ();
while (it != ()) {
    if (*it % 2 == 0) {
        it = (it); // Delete and update it    } else {
        it++;             // Otherwise, it will increase normally    }
}

Reverse traversal(Avoid iterator failure)

for (auto it = (); it != (); ) {
    if (*it % 2 == 0) {
        it = vector<int>::reverse_iterator((() - 1));
    } else {
        it++;
    }
}

3. Iterator failure of other containers

container Insert operation (insert) Delete operation (erase)
vector Possible failure (depending on capacity) Delete and subsequent invalidation
deque Possible failure (start and end) Deleted and nearby invalid
list Will not fail Only deleted invalid
map/set Will not fail Only deleted invalid

4. Summary

  • vectorWhen inserting
    • Possible failure(If reassignment is triggered).
    • How to avoid it:in advancereserve()Or use index.
  • vectorWhen deletion
    • Deleted and subsequent iterators fail
    • The correct way to do it:useeraseReturn value or reverse traversal.
  • Other containers(likelistmap) is usually safer, but still requires caution.

Best Practices

  1. Avoid directly modifying containers during traversal, unless it is explicitly known whether the iterator is valid.
  2. Try to userange-based forOr algorithm (such asremove_if, reduce manual management of iterators.
  3. Used during debugging-D_GLIBCXX_DEBUG(GCC) Detect iterator errors.

The above is the detailed content of the guide to avoid pit failure of C++ iterator. For more information about C++ iterator failure, please pay attention to my other related articles!