Reputation: 23
I have a function that iterates through a vector and calls another function to execute its contents in some manner. As a result of that execution new elements could be added to the vector. Function code is as follows:
void foo() {
for (std::vector<Item*>::iterator it = item_list.begin(); it != item_list.end(); ++it ) {
if (/*some condition*/) {
bar(it);
}
}
}
While I was googling this problem I saw that iterator might get invalidated if resize happens, but the writer was not specific on why nor when or what is the proper way of handling this problem.
Upvotes: 2
Views: 886
Reputation: 56903
As a vector is random access, you can store the distance temporarily and re-create the iterator afterwards:
void foo() {
for (std::vector<Item*>::iterator it = item_list.begin(); it != item_list.end(); ++it ) {
if (/*some condition*/) {
const auto d = std::distance( item_list.begin(), it );
bar(it);
it = item_list.begin();
std::advance( it, d );
}
}
}
The answer assumes that new elements are added after the current position, e.g., at the end. It also assumes that it is desirable that the new elements are also part of the iteration, i.e., they will also be checked against some condition
and bar
will be called if they do match.
Upvotes: 2
Reputation: 4370
According to the documentation, if inserting an element changes the capacity of the vector
, all iterators are invalidated.
To work around this, add new items to a temporary vector
and merge the two after you're done.
Upvotes: 0
Reputation: 1234
Instead of inserting more items on that vector within a interaction, simply create another vector to store all the items and do the resizing while you iterate in this one, then you discard the current one and swap for that updated vector.
That's the standard way to do that.
Upvotes: 0