Question

Is it possible to change the size of a vector in C++11 while iterating over it? Clearly the iterator will be invalidated, but can the following clean syntax still be used?

std::vector<some_type> vec;
for(auto elem : vec) {
   if(condition(elem)) {
      new_elem = function(elem);
      vec.insert(iterator_associated_with_elem+1, new_elem);
   }
   //Don't insert on condition(new_elem)
}

If not, what is the cleanest code to accomplish this task?

Was it helpful?

Solution

No, you can't. The standard mandates that the raged-based for behaves like a given algorithm. This algorithm uses iterators, which get invalidated when you modify the vector.

The simplest way for me is to to use iterators. Note that when we insert, we also reassign the iterator so that we always have a valid iterator:

auto it = vec.begin();
while(it < vec.end()) {
  if (condition(*it)) {
    new_elem = function(*it);
    it = vec.insert(it + 1, new_elem);
  }
  ++it;
}

OTHER TIPS

No, you cannot use this trick, because there is an iterator behind your range loop. Once that iterator is invalidated, you cannot reference it again.

You can use this construct if you exit the loop immediately after the insertion. Otherwise, you need to use an index-based loop that starts at the back, and goes down to zero to avoid "seeing" elements that have been inserted during the execution of the loop.

std::vector<some_type> vec;
for(int i = vec.size()-1 ; i >= 0 ; i--) {
   const some_type& elem(vec[i]);
   if(condition(elem)) {
      vec.insert(vec.begin()+i+1, function(elem));
   }
   //Don't insert on condition(new_elem)
}
std::vector<int> vec = {1, 2, 3, 4, 5};

    for (auto &val : vec)
    {
        static int i = 0;

        if (val == 5)
        {
            vec.insert(vec.begin() + i + 1, 6);
        }
        ++i;
    }

Values of vec will then be: 1 2 3 4 5 6

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top