This program has a runaway error about iterator

76 Views Asked by At

There is a problem with this code. I corrected preb++ to ++preb and it was fine, but I don't know why preb++ can't continue to run. Logically speaking, preb and item point to the same element. But the next cycle will correct it, making preb the element pointed to by item. It should continue to operate as usual. Only the newly added elements will be deleted.

#include <forward_list>
#include <iostream>
using std::forward_list;
using std::cin;
using std::cout;
int main ()
{
    string s1 {"abc"};
    string s2 ={"abc_list"},temp_str; 
    forward_list<string> flis;
    auto preb = flis.before_begin();
    while (cin >> temp_str)
    {
        preb = flis.insert_after(preb,temp_str);
    }
    for (auto &i : flis)
    {
        cout << i << endl;
    }
    preb = flis.before_begin();
    auto it =flis.begin();
    int flag=0;
    while (it != flis.end())
    {
        if ( *it == s1)//compare element
        {
            flis.insert_after(preb,s2);
            it=flis.erase_after(preb++);//the ok code should be it=flis.erase_after(++preb)
            flag=1;
            //cout << "22222222"<< endl;//debug
        }
        else
        {

            preb = it ;
            ++it;
        }
    }
    //cout << "1111111111" <<endl; //debug
    if (!flag)
    {
        flis.insert_after(preb,s2);
    }
    for (auto &i : flis)
    {
        cout << i << endl;
    }
    return 0;
}

Why is it not running properly?

1

There are 1 best solutions below

2
On

In it=flis.erase_after(preb++);

  • preb is incremented and becomes the iterator to the erased node
  • you erase the node, which also invalidates preb

In it=flis.erase_after(++preb);

  • preb is incremented and becomes the iterator to before the erased node
  • you erase the node after the new preb, and preb remains valid

Note the following on iterator invalidation:

None of the overloads of insert_after shall affect the validity of iterators and references, and erase_after shall invalidate only iterators and references to the erased elements.

- [forward.list.modifiers] p1

Always keep iterator invalidation in mind. You could implement the first version in two steps:

it=flis.erase_after(preb);
++preb;

This would work because preb would only be incremented after the erasure takes place, so it wouldn't get invalidated by it.