Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does resizing a vector invalidate iterators?

Tags:

I found that this C++ code:

vector<int> a; a.push_back(1); a.push_back(2); vector<int>::iterator it = a.begin(); a.push_back(4); cout << *it; 

print some big random number; but if you add a.push_back(3) between 3rd and 4th lines, it will print 1. Can you explain it to me?

like image 947
mike Avatar asked Oct 26 '09 13:10

mike


People also ask

What happens when you resize a vector?

The C++ function std::vector::resize() changes the size of vector. If n is smaller than current size then extra elements are destroyed. If n is greater than current container size then new elements are inserted at the end of vector.

What invalidates an iterator?

An Iterator becomes invalidate when the container it points to changes its shape internally i.e. move elements from one location to another and the initial iterator still points to old invalid location. Iterator invalidation in vector happens when, An element is inserted to vector at any location.

What causes iterator invalidation?

Iterator Invalidation in C++ When the container to which an Iterator points changes shape internally, i.e. when elements are moved from one position to another, and the initial iterator still points to the old invalid location, then it is called Iterator invalidation. One should be careful while using iterators in C++.

How can we avoid iterator invalidation?

To avoid invalidation of references to elements you can use a std::deque if you do not insert or erase in the middle. To avoid invalidation of iterators you can use a std::list.


1 Answers

Edited with more careful wording

yes, resizing a vector might invalidate all iterators pointing into the vector.

The vector is implemented by internally allocating an array where the data is stored. When the vector grows, that array might run out of space, and when it does, the vector allocates a new, bigger, array, copies the data over to that, and then deletes the old array.

So your old iterators, which point into the old memory, are no longer valid. If the vector is resized downwards (for example by pop_back()), however, the same array is used. The array is never downsized automatically.

One way to avoid this reallocation (and pointer invalidation) is to call vector::reserve() first, to set aside enough space that this copying isn't necessary. In your case, if you called a.reserve(3) before the first push_back() operation, then the internal array would be big enough that the push_back's can be performed without having to reallocate the array, and so your iterators will stay valid.

like image 173
jalf Avatar answered Sep 28 '22 10:09

jalf