2

I am removing the elements from map by using erase in the following way but it is not working properly. Why? It is not removing all.

float nw_cut=80.0;
for(it=nw_tot1.begin();it!=nw_tot1.end();it++)
{
    float f=(float) ((float) it->second/lines)*100.0;
    if ( f < nw_cut )
    {
        nw_tot1.erase(it);
    }
}
doctorlove
  • 18,872
  • 2
  • 46
  • 62
Pavan
  • 507
  • 1
  • 3
  • 15
  • There are similar questions e.g. http://stackoverflow.com/questions/4636182/problem-with-stdmapiterator-after-calling-erase – doctorlove Jun 25 '13 at 11:30

3 Answers3

8

From std::map::erase():

References and iterators to the erased elements are invalidated. Other references and iterators are not affected.

If erase(it) is called then it is invalidated, and it is then used by the for loop causing undefined behaviour. Store the return value of erase(), which returns an iterator to the next element after the erased element (since c++11), and only increment if erase() was not called:

for(it = nw_tot1.begin(); it != nw_tot1.end();)
{
    float f=(float) ((float) it->second/lines)*100.0;

    if ( f < nw_cut ) it = nw_tot1.erase(it);
    else ++it;
}

In c++03 (and c++11 also) this could be accomplished with:

for(it = nw_tot1.begin(); it != nw_tot1.end();)
{
    float f=(float) ((float) it->second/lines)*100.0;

    if ( f < nw_cut ) nw_tot1.erase(it++);
    else ++it;
}
hmjd
  • 120,187
  • 20
  • 207
  • 252
1

You should do something like this:

float nw_cut=80.0;
for(it=nw_tot1.begin();it!=nw_tot1.end();)
{
    float f=(float) ((float) it->second/lines)*100.0;
    it_temp = it;    //store it in temp variable because reference is invalidated when you use it in erase.
    ++it;
    if ( f < nw_cut ) {
        nw_tot1.erase(it_temp);
    }
}
Aman Deep Gautam
  • 8,091
  • 21
  • 74
  • 130
0
for(it = nw_tot1.begin(); it != nw_tot1.end();)
{
    float f=(float) ((float) it->second/lines)*100.0;

    if ( f < nw_cut ) it = nw_tot1.erase(it);
    else ++it;
}
BlackMamba
  • 10,054
  • 7
  • 44
  • 67