A.H
A.H

Reputation: 29

The relationship between "reserve" and "iterator" with std::vector

When using the reserve() method with this iterator object, the program produces an unexpected error.

When I use the reserve() method without it, it works as expected, but when I use iterator, it doesn’t work at all.

the code that works:

vector <int> nums{1,2,3,4,5}, numsT{};

numsT.reserve(50);
numsT.insert(numsT.begin(), nums.begin(), nums.end() - 1);

The code that does not work:

vector <int> nums{ 1,2,3,4,5 }, numsT{};
vector <int>::iterator first{ nums.begin() }, last{ nums.end() - 1 }, position{ numsT.begin() };
 
numsT.reserve(50);
numsT.insert(position, first, last);

Upvotes: 0

Views: 105

Answers (2)

wohlstad
wohlstad

Reputation: 29009

TL;DR:
The problem has nothing to do with the fact that you use the iterator type explicitly, but only with the fact that you initialize it before calling reserve.

More info:

Regarding the 2nd snippet:

As you can see in the std::vector::reserve documentation:

If new_cap is greater than capacity(), all`iterators (including the end() iterator) and all references to the elements are invalidated.

In your case you initialize position as numsT.begin(), but then reserve numsT with 50 elements. Since it was empty it is almost certain that the new capacity (at least 50) exceeds the exisiting one, and so position is invalidated.

Therefore the subsequent call to:

numsT.insert(poistion, first, last);

Invokes undefined behavior, since position is not valid.

It will work if you initialize first after the call to reserve:

vector<int> nums{ 1,2,3,4,5 }, numsT{};
vector<int>::iterator first{ nums.begin() }, last{ nums.end() - 1 };
numsT.reserve(50);
vector<int>::iterator position{ numsT.begin() };
numsT.insert(position, first, last);

The reason the 1st snippet works:

In the first snippet you call insert with numsT.begin(). It is evaluated at this point when reserve already took place and is therefore valid.


A side note:
It is better to avoid using namespace std; - see more about it here.

Upvotes: 6

BoP
BoP

Reputation: 3160

cppreference says:

If new_cap is greater than capacity(), all iterators (including the end() iterator) and all references to the elements are invalidated.

So, if a reallocation happens (which is the case here) the iterator position is no longer valid. A call to numsT.begin() would return a different value after the reserve.

Upvotes: 0

Related Questions