Deleting from std::list

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Martin Magnusson

    Deleting from std::list

    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_b ack(1);
    the_list.push_b ack(2);
    the_list.push_b ack(3);
    the_list.push_b ack(4);
    list<int>::iter ator 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?

  • Victor Bazarov

    #2
    Re: Deleting from std::list

    "Martin Magnusson" <loveslave@frus tratedhousewive s.zzn.com> wrote...[color=blue]
    > 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_b ack(1);
    > the_list.push_b ack(2);
    > the_list.push_b ack(3);
    > the_list.push_b ack(4);
    > list<int>::iter ator i = the_list.end();
    > i--;
    > cout << the_list.size() ;
    > for (std::list<int> ::iterator j = i;
    > j != the_list.end();
    > ++j)[/color]

    What's the purpose of ++j here?
    [color=blue]
    > {
    > 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?[/color]

    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


    Comment

    • Mike Wahler

      #3
      Re: Deleting from std::list

      Martin Magnusson <loveslave@frus tratedhousewive s.zzn.com> wrote in message
      news:bi3l02$fe7 $1@green.tninet .se...[color=blue]
      > 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_b ack(1);
      > the_list.push_b ack(2);
      > the_list.push_b ack(3);
      > the_list.push_b ack(4);
      > list<int>::iter ator i = the_list.end();
      > i--;
      > cout << the_list.size() ;
      > for (std::list<int> ::iterator j = i;[/color]

      So now 'j' points to the last element (with value of 4.)
      [color=blue]
      > j != the_list.end();
      > ++j)
      > {
      > cout << ".";
      > j = the_list.erase( j );[/color]

      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.

      [color=blue]
      > }
      > 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?[/color]


      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



      Comment

      • John Harrison

        #4
        Re: Deleting from std::list


        "Martin Magnusson" <loveslave@frus tratedhousewive s.zzn.com> wrote in message
        news:bi3l02$fe7 $1@green.tninet .se...[color=blue]
        > 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_b ack(1);
        > the_list.push_b ack(2);
        > the_list.push_b ack(3);
        > the_list.push_b ack(4);
        > list<int>::iter ator 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?
        >[/color]

        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


        Comment

        • Martin Magnusson

          #5
          Re: Deleting from std::list

          Thanks for your answers, all of you! I wasn't aware that the ++j was
          executed before the comparison j!=the_list.end ().


          Comment

          • Stuart Golodetz

            #6
            Re: Deleting from std::list

            "Martin Magnusson" <loveslave@frus tratedhousewive s.zzn.com> wrote in message
            news:bi59l9$jac $1@green.tninet .se...[color=blue]
            > Thanks for your answers, all of you! I wasn't aware that the ++j was
            > executed before the comparison j!=the_list.end ().[/color]

            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_ba ck();

            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.


            Comment

            Working...