Iterators are important in C++ programming as they enable the traversal and manipulation of the container elements without exposing their structure. However, if the container’s structure is changed, then the iterator invalidation occurs. In this article, we will discuss the iterator and containers, and iterator invalidation rules in C++.
Table of Contents:
Understanding Iterators in C++
Iterators are objects in C++ that allow the elements to traverse in a container such as an array, vector, or list without exposing the underlying structure. They provide a uniform interface for accessing the elements that support various operations such as incrementing, dereferencing, and comparing, which allows you to write reusable codes. There are different types of iterators in C++, such as input iterators, output iterators, forward iterators, bidirectional iterators, and random access iterators.
Example:
Output:
The code shows how a std::vector of integers and an iterator of that vector is created, and the iterator is used to traverse and print all its elements. Also, the iterator moves from begin() to end() which dereferences each element of the vector to be displayed.
Understanding Containers in C++
C++ containers are a part of the Standard Template Library(STL) which efficiently stores and manages the collections of data. There are four main types of containers in C++: sequence containers (vector, list, queue), associative containers (set, map), unordered containers (unordered_set, unordered_map), and adapters (stack, queue), and each type of container performs different operations.
Example:
Output:
The code shows how the sequence and associative containers print the elements of a vector and a set. Also, the vector maintains the original order, while the set stores the elements in sorted order.
What is Iterator Invalidation in C++?
An iterator invalidation occurs in C++ when an operation is performed on a container, and it changes the structure of the container in such a way that makes the iterator invalid or points to unintended memory, and accessing an invalidated iterator can lead to undefined behaviour.
Example:
Output:
The code shows how the iterator invalidation occurs by changing a vector after creating its iterator, and the push_back(6) operation reallocates the memory, which makes the iterator invalid and causes undefined behaviour if you try to access it.
Iterator Invalidation Rules in C++
Below is a table format of the Iterator Invalidation Rules for better understanding.
Operation |
Container |
Invalidation Rules |
Insertion | Vector | All iterators pointing to elements before the insertion point remain unaffected; all others are invalidated. If insertion exceeds capacity, all iterators are invalidated. |
| Deque | All iterators and references are invalidated unless the inserted element is at an end (front or back), where only iterators are invalidated, and references remain unaffected. |
| List | All iterators and references remain unaffected. |
| Set, Map, Multiset, Multimap | All iterators and references remain unaffected. |
Erasure | Vector | Every iterator and reference after the point of erasure is invalidated. |
| Deque | All iterators and references are invalidated unless the erased element is at an end (front or back), where only iterators and references to the erased element are invalidated. |
| List | Only the iterators and references to the erased element are invalidated. |
| Set, Map, Multiset, Multimap | Only the iterators and references to the erased elements are invalidated. |
Resizing | Vector, Deque, List | The same rules as insertion and erasure apply. If resizing causes reallocation (e.g., std::vector), all iterators may become invalidated. |
Conclusion
As we have discussed, invalidation rules of iterators in C++ can be important since they allow for traversing the elements of containers such as arrays, vectors, and lists in a way that does not expose the internal nature of those containers. Iterator invalidation occurs when the structure of a container is modified (insertion, deletion, or resizing), and that can lead to undefined behaviour. Therefore, you have to know well the insertion, deletion, and resizing rules on the containers to be able to write C++ codes that are not only efficient and reusable but also safe to run.
Iterator Invalidation Rules for C++ Containers – FAQs
1. What are iterators in C++?
Iterators are objects in C++ that allow the elements to traverse in a container such as an array, vector, or list without exposing the underlying structure.
2. What types of iterators exist in C++?
There are different types of iterators in C++, such as input iterators, output iterators, forward iterators, bidirectional iterators, and random access iterators.
3. What are C++ containers?
C++ containers are a part of the Standard Template Library(STL) which efficiently stores and manages the collections of data.
4. What is iterator invalidation?
Iterator invalidation occurs when a container’s structure is changed (through insertion, deletion, or resizing), which causes undefined behaviour.
5. How can I avoid iterator invalidation?
You can avoid iterator invalidation by understanding and implementing the rules of iterator invalidation.