Notice the vector list set map member functions erase

  • 2020-04-02 01:39:22
  • OfStack


#include <iostream>
#include <vector>
#include <list>
#include <iterator>
using namespace std;
void Remove1(vector<int> &vec, int num)
{
 vector<int>::iterator iter;
 for (iter=vec.begin(); iter!=vec.end(); ++iter)
 {
  if (*iter == num)
  {
   vec.erase(iter);
  }
 }
}
void Remove2(list<int> &lst, int num)
{
 list<int>::iterator iter;
 for (iter=lst.begin(); iter!=lst.end(); ++iter)
 {
  if (*iter == num)
  {
   lst.erase(iter);
  }
 }
}
int main(void)
{
 int arr[] = {1, 3, 5, 5, 7, 9};
 int num = sizeof(arr) / sizeof(arr[0]);
 vector<int> vec(arr, arr+num);
 list<int> lst(arr, arr+num);
 Remove1(vec, 5);
 copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));

 //Remove2(lst, 5);
 //copy(lst.begin(), lst.end(), ostream_iterator<int>(cout, " "));
 return 0;
}

Look at Remove1 and Remove2 above. These two functions delete all num elements in the container.

They compile with no problems, but run with problems:
First comment Remove2 these two lines, compile run, the result is: 1, 3, 5, 7, 9
It's obviously wrong, because there's still a 5 left. The reason for this is that after vec.erase, iter adds itself, and the next for loop, ++iter, bypasses the element adjacent to the deleted element.

Take a look at Remove2 again, comment out Remove1, remove the comment for Remove2.
Vs2005 Expression:list iterator not incrementable, indicating a problem with the list iterator ++iter.
List is a two-way linked list, iter failed after erase(iter), printf("0x%x", iter); With a result of 0, only the return value of erase can point to the next element.

The correct usage of Remove1 is: vec.erase(remove(vec.begin(), vec.end(), 5), vec.end());
The correct use of Remove2 is: lst.remove(5);

Here's another way to write it:


void Remove1(std::vector<int> &vec, int num)
{
 std::vector<int>::iterator iter = vec.begin();
 while (iter != vec.end())
 {
  if (*iter == num)
  {
   iter = vec.erase(iter);
  }
  else
  {
   ++iter;
  }
 }
}
//Delete a class of elements, such as an even number
void Remove3(std::set<int>& sets)
{
 std::set<int>::iterator iter = sets.begin();
 while (iter != sets.end())
 {
  if (0 == (*iter)%2)
  {
   //Notice I can't write plus plus iter, and I'll show you why
   sets.erase(iter++);
  }
  else
  {
   ++iter;
  }
 }
}
void Remove4(std::map<int, int>& maps)
{
 std::map<int, int>::iterator iter = maps.begin();
 while (iter != maps.end())
 {
  if (0 == (iter->first)%2)
  {
   maps.erase(iter++);
  }
  else
  {
   ++iter;
  }
 }
}

Set and map are implemented by the red-black tree, and the iterator fails when erase occurs, which means that we keep a copy of the iterator before it fails, from which we can proceed to the next element. I ++ and ++ I obviously meet our requirements so I ++ on erase


Related articles: