Step 6 of 7
Iterator invalidation
Changing a container can invalidate iterators, pointers and references into it. Using one afterwards is undefined behavior, and one of the most common C++ bugs in real code:
| Container | What invalidates |
|---|---|
vector |
push_back that reallocates: everything. erase: the erased element and everything after it |
deque |
inserting at either end invalidates iterators (but not references) |
list, map, set |
only iterators to erased elements |
The safe erase-while-looping pattern uses the iterator erase returns (the element after the removed one):
for (auto it = v.begin(); it != v.end(); ) {
if (dead(*it)) it = v.erase(it); // don't ++ after erasing
else ++it;
}
(For vectors, std::erase_if(v, pred) does this in one efficient call, as you saw in the algorithms module. The loop pattern is still what you need for map and for loops that do more than erase.)
Your turn: write int remove_expired(std::map<std::string, int>& sessions, int now) that erases every session whose expiry time is <= now, returning how many were removed. Use the loop pattern.
Previous: Iterators Next: Challenge: callbacks with std::function