Iterator invalidation rules for std::deque

When do std::deque operations invalidate iterators?

An iterator is considered invalidated if it no longer points to the same element it originally pointed to.

For std::deque, the iterator invalidation rules are as follows:

  1. End iterators: The end iterator (the one returned by end()) is always invalidated when the deque is modified.
  2. Insertion: Insertion in the middle of the deque invalidates all iterators. Insertion at either end (using push_front(), emplace_front(), push_back(), emplace_back()) only invalidates the end iterator.
  3. Erasure: Erasing an element in the middle of the deque invalidates all iterators. Erasing an element at either end (using pop_front() or pop_back()) only invalidates the end iterator and the iterators to the erased elements.
  4. Clear: Calling clear() invalidates all iterators.
  5. Swap: Calling swap() invalidates all iterators.

Here's an example demonstrating iterator invalidation:

#include <deque>
#include <iostream>

int main() {
  std::deque<int> d{1, 2, 3, 4, 5};

  auto it = d.begin();
  auto end = d.end();

  d.push_front(0);  

  // This is fine, it still points to the element 1
  std::cout << *it << "\n"; 
  
  // This is invalid, end iterator is invalidated
  std::cout << *(end - 1) << "\n"; 

  d.insert(it + 2, 10);  
  // This is invalid, it no longer points to 1
  std::cout << *it << "\n"; 
}

The previous example results in undefined behaviour. With debug flags enabled, the compiler may detect the problem and throw a run time error:

cannot deference out of range deque iterator

To avoid issues with iterator invalidation, it's often best to reacquire iterators after any operation that could potentially invalidate them.

Double-Ended Queues using std::deque

A guide to double-ended queues - a structure that behaves like a vector, specialised for manipulating objects at the edges of the collection

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Performance differences between std::vector and std::deque
When should I use a std::deque instead of a std::vector for optimal performance?
How std::deque is implemented internally
How does a std::deque store its elements in memory?
Exception safety of std::deque operations
Which std::deque operations are exception-safe?
Benefits of using emplace over insert
What are the advantages of using emplace_front() or emplace_back() instead of push_front() or push_back()?
Thread safety of std::deque
Is std::deque thread-safe? Can multiple threads access a deque concurrently?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant