C++ STL Common Container Delete Operational Notes

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;
}

Added by bossman on Mon, 08 Jul 2019 04:21:29 +0300