2

Is it possible to iterate in one single step through elements of a vector, while deleting some of the elements, to prevent repeated processing? (I know the fragment is bogus, but illustrates what I want)

std::vector<MyRecord*>* BLV = GetVector();
for (std::vector<MyRecord*>::iterator it = BLV->begin(); it != BLV->end(); ++it)
{
  MyRecord* BL = *it;
  if(Selected)
  { 
    delete BL;
    BLV->erase(it);
  }
}
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
katang
  • 2,474
  • 5
  • 24
  • 48

2 Answers2

8

Note std::vector::erase will invalidate the iterator to the element to be erased, and then ++it; will lead to UB.

Invalidates iterators and references at or after the point of the erase, including the end() iterator.

You can use the return value of erase().

Iterator following the last removed element. If the iterator pos refers to the last element, the end() iterator is returned.

then change the loop to

for (std::vector<MyRecord*>::iterator it = BLV->begin(); it != BLV->end(); )
{
  MyRecord* BL = *it;
  if(Selected)
  { 
    delete BL;
    it = BLV->erase(it);
  } else
  {
    ++it;
  }
}
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
1

songyuanyao already gave you a nice answer: In short, you have to reset your iterator to the value returned by erase.

However, if applicable, I'd suggest using a vector of unique_ptr's and the erase-remove idiom (which is also more efficient, as it only moves the elements once).

std::vector<std::unique_ptr<MyRecord>>* BLV = GetVector();
BLV->erase(
    std::remove_if(BLV->begin(), BLV->end(), 
        [&](const std::unique_ptr<MyRecord>& rec) { return Selected; }
    ),
    BLV->end()
);
MikeMB
  • 20,029
  • 9
  • 57
  • 102