user100593
user100593

Reputation: 23

Expanding vector while iterating through it

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

Answers (3)

Daniel Frey
Daniel Frey

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

Bart van Nierop
Bart van Nierop

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

CrociDB
CrociDB

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

Related Questions