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