Reputation: 83
int main(){
vector<int> veclist;
veclist.push_back(90);
veclist.push_back(80);
veclist.push_back(70);
vector<int>::iterator it;
it=veclist.begin();
veclist.insert(it,20);
cout << *it << endl; // prints 20
it++;
veclist.insert(it,99);
cout << *it <<endl; // line abc : prints 0
}
Hi, I am working with vectors and iterators in C++. In the above code, why is "line abc" printing 0. Shouldn't it be printing 99 instead? When I print all the vector elements using a for loop, 99 is also printed but why isn't line abc doing so? I am dereferencing the iterator *it, and I expected it to hold the element 99.
Upvotes: 2
Views: 988
Reputation: 172924
Because std::vector<T,Allocator>::insert
causes iterator invalidation.
Causes reallocation if the new
size()
is greater than the oldcapacity()
. If the newsize()
is greater thancapacity()
, all iterators and references are invalidated. Otherwise, only the iterators and references before the insertion point remain valid. The past-the-end iterator is also invalidated.
That means after insert
's invocation, it
has been invalidated. Usage of it like *it
or it++
leads to UB.
You should assign it
to the return value of insert
, which is the iterator pointing to the inserted value. e.g.
vector<int>::iterator it;
it=veclist.begin();
it=veclist.insert(it,20);
cout << *it << endl; // prints 20
it++;
it=veclist.insert(it,99);
cout << *it <<endl; // prints 99
Upvotes: 1
Reputation: 4176
When inserting in a vector, all previous iterators are invalidated. Everything after veclist.insert(it,20)
is undefined behavior.
To be more precise about what happens under the hood the reason the first print works and the second doesn't is because of the allocated std::vector
capacity. Most implementations allocate only 2^N memory chunks.
Therefore, initial vector has capacity of 4. When you increase size from 3 to 4, all previous iterators happen to remain valid. However, when size grows from 4 to 8, memory is copied in a new region, therefore you're accessing deleted memory.
To solve this, you can simply use the result of std::vector::insert
, as the valid iterator pointing to the inserted element:
e.g.
it = veclist.insert(it,20);
Upvotes: 1