I have a vector that I am iterating over. While iterating, I may append new values to the vector. It looks something like:
struct Foo { bool condition; }; void AppendToVec(vector<Foo>& v) { ... v.push_back(...); } vector<Foo> vec; ... for (vector<Foo>::size_type i = 0; i < vec.size(); ++i) { if (vec[i].condition) AppendToVec(vec); }
This works fine, and in fact elegantly handles the case where the newly appended elements recursively require even more elements to be added, but it feels a little fragile. If someone else comes along and tweaks the loop, it can easily be broken. For example:
//No longer iterates over newly appended elements vector<Foo>::size_type size = vec.size(); for (vector<Foo>::size_type i = 0; i < size; ++i) { if (vec[i].condition) AppendToVec(vec); }
or
//Vector resize may invalidate iterators for (vector<Foo>::iterator i = vec.begin(); i != vec.end(); ++i) { if (vec->condition) AppendToVec(vec); }
Are there any best practices to handle cases like this? Is commenting the loop with a "Warning: This loop is intentionally appends to the vector while iterating. Change cautiously" the best approach? I am open to switching containers too if that makes things more robust.
How do you append to a Vector in C++? Appending to a vector means adding one or more elements at the back of the vector. The C++ vector has member functions. The member functions that can be used for appending are: push_back(), insert() and emplace().
To insert/append a vector's elements to another vector, we use vector::insert() function.
Read a value into x , use that value as index into the vector, and increase the value at that index. So if the input for x is 1 , then it's equivalent to vec[1]++ , that is the second (remember that indexes are zero based) will be increased by one.
Elements can be added in the middle of a Vector by using the java. util. Vector. insertElementAt() method.
My approach to this problem is often to create a queue to which I add any new elements, and then after iterating over the original container, process the elements in the queue and/or append them to the original.
The good points to this approach are that what is going on is obvious, and it works in scenarios where multiple threads could be enqueuing new elements.
If someone else comes along and tweaks the loop, it can easily be broken.
Then don't use a for
loop, use a while
loop instead. For me, a for
loop always implies a simple, iterative loop using a counter. However, if I encounter a while
loop, I feel like things must have been too complicated to to express them in a simple for
loop. I will look closer and I'm more careful with "optimizing" while
loops than with for
loops.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With