How to iterate vector in a loop and delete items from it?

Printer-friendly versionPDF version
You can't just iterate vector in a for loop and delete the item pointed by the iterator and increment that iterator at the end of the loop, as after deleting the item from the vector, the iterator is invalidated.

The crude way of deleting the items in a vector is:

typedef std::vector<std::string> string_vector;
typedef std::vector<std::string>::iterator string_vector_iterator;

string_vector_iterator iter = m_vPaths.begin();
while (iter != m_vPaths.end())
{
  if(::DeleteFile(iter->c_str()))
  {
    // erase returns the new iterator to next position
    iter = m_vPaths.erase(iter);
  }
  else
  {
    // if erase is not called, then we manually increment
    // the iterator to next position
    ++iter;
  }
}

The ideal way of removing items from a vector is using the STL algorithms: remove_if and erase.
#include <algorithm> // for remove_if
#include <functional> // for unary_function

struct delete_file : public std::unary_function<const std::string&, bool>
{
  bool operator()(const std::string& strPath) const
  {
    return ::DeleteFile(strPath.c_str());
  }
}

m_vPaths.erase(std::remove_if(m_vPaths.begin(), m_vPaths.end(), delete_file()),
    m_vPaths.end());

Remove_if removes from the range [first, last) every element x such that pred(x) is true. That is, remove_if returns an iterator new_last such that the range [first, new_last) contains no elements for which pred is true. The iterators in the range [new_last, last) are all still dereferenceable, but the elements that they point to are unspecified. Remove_if is stable, meaning that the relative order of elements that are not removed is unchanged.
No votes yet