C/C++ programmers are certainly familiar with STL containers. The following is a summary of the precautions for erase operation of common containers:
vector
vector containers are implemented by arrays and are distributed continuously in memory. Inserting or erase operations on them involve shifting elements after insertion or deletion points, so iterator s after insertion or deletion points will fail.
iterator erase( iterator pos ); iterator erase( const_iterator pos );
Looking at STL helps you to know that the return value of the vector::erase function is the next iterator of the current iterator pointer.
Iterator following the last removed element. If the iterator pos
refers to the last element, the end() iterator is returned.
So the erase operation of vector s can take the following form:
//Delete the element whose value in vector 1 equals num for(; it != vector1.end(); ) { if(num == *it) it = vector1.erase(it); else ++it; }
list
STL list container is implemented by two-way linked list, using discontinuous memory space to store elements. inser will not cause any iterator failure, erase will delete the point of the iterator failure, but does not affect other iterators. Its erase function is similar to vector, the function return value is the next iteration of the current iterator pointer. However, due to the different underlying implementations, list deletion can be done in a more flexible way.
//Delete the element whose value in list1 equals num for(; it != list1.end(); ) { if(num == *it) it = list1.erase(it); //list1.erase(it++); //also OK else ++it; }
map
The bottom of STL map container is implemented by red-black tree, that is to say, it is a balanced binary tree. Its inser tion and deletion effect is similar to that of list. Insert will not cause any iterator failure, erase will only cause the iterator of deletion point to fail, other iterators will not be affected. Code writing is similar to list:
// Delete all key s in Map 1 as odd elements for(auto it = map1.begin(); it != map1.end(); ) { if(it->first % 2 == 1) //it = map1.erase(it); map1.erase(it++); else ++it; }
Other containers, such as dequeue, use vector for reference. Set can use map for reference. Here's the test code.
//To complie: g++ -o test test.cpp -std=c++11
#include <iostream>
#include <algorithm>
#include <string>
#include <list>
#include <vector>
#include <map>
using std::cout;
void test1()
{
std::vector<int> vi{1,2,3,3,3,5};
int num = 3;
std::vector<int>::iterator it = vi.begin();
//erase element whose value is 3
for(; it != vi.end(); ) {
if(num == *it)
it = vi.erase(it);
else
++it;
}
std::copy(vi.begin(), vi.end(), std::ostream_iterator<int>(cout, "\t"));
cout << '\n';
}
void test2()
{
std::list<int> li{1,2,3,3,3,5};
int num = 3;
std::list<int>::iterator it = li.begin();
//erase element whose value is 3
for(; it != li.end(); ) {
if(num == *it)
//it = li.erase(it);
li.erase(it++);
else
++it;
}
std::copy(li.begin(), li.end(), std::ostream_iterator<int>(cout, "\t"));
cout << '\n';
}
void test3()
{
std::map<int, std::string> map1 = {{1, "one"}, {2, "two"}, {3, "three"},
{4, "four"}, {5, "five"}, {6, "six"}};
// erase all odd numbers from map1
for(auto it = map1.begin(); it != map1.end(); ) {
if(it->first % 2 == 1)
//it = map1.erase(it);
map1.erase(it++);
else
++it;
}
for(auto& p : map1) {
cout << p.second << ' ';
}
cout << '\n';
}
int main() {
// test1();
// test2();
test3();
return 0;
}