Deleting from std::list

Discussion in 'C++' started by Martin Magnusson, Aug 22, 2003.

  1. I know a similar question was recently posted here, but after trying the
    solutions in that thread I still have problems.

    list<int> the_list;
    the_list.push_back(1);
    the_list.push_back(2);
    the_list.push_back(3);
    the_list.push_back(4);
    list<int>::iterator i = the_list.end();
    i--;
    cout << the_list.size();
    for (std::list<int>::iterator j = i;
    j != the_list.end();
    ++j)
    {
    cout << ".";
    j = the_list.erase( j );
    }
    cout << the_list.size();

    What happens is this: j goes to the end of the list and erases the last
    element. By then I would have thought that j would be set to nodes.end()
    and the loop would terminate, but instead it seems that the loop keeps
    running, erasing all of the list. The output of the above code is
    "4....0". What am I doing wrong?
    Martin Magnusson, Aug 22, 2003
    #1
    1. Advertising

  2. "Martin Magnusson" <> wrote...
    > I know a similar question was recently posted here, but after trying the
    > solutions in that thread I still have problems.
    >
    > list<int> the_list;
    > the_list.push_back(1);
    > the_list.push_back(2);
    > the_list.push_back(3);
    > the_list.push_back(4);
    > list<int>::iterator i = the_list.end();
    > i--;
    > cout << the_list.size();
    > for (std::list<int>::iterator j = i;
    > j != the_list.end();
    > ++j)


    What's the purpose of ++j here?

    > {
    > cout << ".";
    > j = the_list.erase( j );
    > }
    > cout << the_list.size();
    >
    > What happens is this: j goes to the end of the list and erases the last
    > element. By then I would have thought that j would be set to nodes.end()
    > and the loop would terminate, but instead it seems that the loop keeps
    > running, erasing all of the list. The output of the above code is
    > "4....0". What am I doing wrong?


    Why are you increasing 'j'? Once 'j' is set to the_list.end(),
    using ++ for it causes undefined behaviour. If an iterator is
    "one past the end", it is not dereferenceable, which is a pre-
    condition for ++.

    Victor
    Victor Bazarov, Aug 22, 2003
    #2
    1. Advertising

  3. Martin Magnusson

    Mike Wahler Guest

    Martin Magnusson <> wrote in message
    news:bi3l02$fe7$...
    > I know a similar question was recently posted here, but after trying the
    > solutions in that thread I still have problems.
    >
    > list<int> the_list;
    > the_list.push_back(1);
    > the_list.push_back(2);
    > the_list.push_back(3);
    > the_list.push_back(4);
    > list<int>::iterator i = the_list.end();
    > i--;
    > cout << the_list.size();
    > for (std::list<int>::iterator j = i;


    So now 'j' points to the last element (with value of 4.)

    > j != the_list.end();
    > ++j)
    > {
    > cout << ".";
    > j = the_list.erase( j );


    Now 'j' == the_list.end()
    We go back to the top of the loop, where 'j' is incremented.
    (past end()). Heaven knows what the 'value' of 'j' is now,
    but it's not equal to 'end()'. So the body of the loop
    executes again. :)

    I think we have undefined behavior here.


    > }
    > cout << the_list.size();
    >
    > What happens is this: j goes to the end of the list and erases the last
    > element. By then I would have thought that j would be set to nodes.end()
    > and the loop would terminate, but instead it seems that the loop keeps
    > running, erasing all of the list. The output of the above code is
    > "4....0". What am I doing wrong?



    Try:

    for (std::list<int>::iterator j = i;
    j != the_list.end();
    j = the_list.erase(j))
    {
    cout << ".";
    }

    or

    for (std::list<int>::iterator j = i;
    j != the_list.end();
    /* no iteration expression */ )
    {
    cout << ".";
    j = the_list.erase(j);
    }

    Your '++j' was overwriting the return from erase that
    you stored in 'j'.

    I must admit it did take me a few minutes to realize
    what was going on. :)

    HTH,
    -Mike
    Mike Wahler, Aug 22, 2003
    #3
  4. "Martin Magnusson" <> wrote in message
    news:bi3l02$fe7$...
    > I know a similar question was recently posted here, but after trying the
    > solutions in that thread I still have problems.
    >
    > list<int> the_list;
    > the_list.push_back(1);
    > the_list.push_back(2);
    > the_list.push_back(3);
    > the_list.push_back(4);
    > list<int>::iterator i = the_list.end();
    > i--;
    > cout << the_list.size();
    > for (std::list<int>::iterator j = i;
    > j != the_list.end();
    > ++j)
    > {
    > cout << ".";
    > j = the_list.erase( j );
    > }
    > cout << the_list.size();
    >
    > What happens is this: j goes to the end of the list and erases the last
    > element. By then I would have thought that j would be set to nodes.end()
    > and the loop would terminate, but instead it seems that the loop keeps
    > running, erasing all of the list. The output of the above code is
    > "4....0". What am I doing wrong?
    >


    But that isn't the solution that was posted recently. If you really tried
    the solution posted recently you would have more luck.

    Your problem is that j is set to nodes.end(), but what is the next thing you
    do? ++j of course!

    This is the correct solution.

    for (std::list<int>::iterator j = i;
    j != the_list.end();
    )
    {
    cout << ".";
    j = the_list.erase( j );
    }

    Note that ++j has disappeared.

    john
    John Harrison, Aug 22, 2003
    #4
  5. Thanks for your answers, all of you! I wasn't aware that the ++j was
    executed before the comparison j!=the_list.end().
    Martin Magnusson, Aug 22, 2003
    #5
  6. "Martin Magnusson" <> wrote in message
    news:bi59l9$jac$...
    > Thanks for your answers, all of you! I wasn't aware that the ++j was
    > executed before the comparison j!=the_list.end().


    A couple more things:

    1)

    If you really just want to remove the last element of a list, you're better
    off just writing:

    the_list.pop_back();

    2)

    Regarding for loops, if you have something like this:

    for(int i=0; i<3; ++i)
    {
    std::cout << i << ' ';
    }

    What actually happens is something like this (using an "infinite" while
    loop, to make things clear):

    int i = 0;
    while(1)
    {
    if(!(i < 3)) break;
    std::cout << i << ' ';
    ++i;
    }

    Hope that clarifies things a bit?

    Cheers,

    Stuart.
    Stuart Golodetz, Aug 22, 2003
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    6
    Views:
    627
    Jim Langston
    Oct 30, 2005
  2. Markus Svilans

    Deleting items from std::list

    Markus Svilans, Jun 26, 2006, in forum: C++
    Replies:
    25
    Views:
    1,399
    Robbie Hatley
    Jun 28, 2006
  3. Andy
    Replies:
    3
    Views:
    476
    James Kanze
    Jun 8, 2007
  4. Juha Nieminen
    Replies:
    22
    Views:
    987
    Kai-Uwe Bux
    Oct 12, 2007
  5. lallous
    Replies:
    5
    Views:
    359
    lallous
    Apr 24, 2008
Loading...

Share This Page