Thread: List Iterators, erase() -- help

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Registered User
    Join Date
    Aug 2010
    Location
    Rochester, NY
    Posts
    196
    Right, so that fixes it:

    Code:
    for (iter = myList.begin() ; iter != myList.end() ; ++iter)
    {
         std::cout << (*iter) << std::endl;
         if ((*iter) == 5)
              iter = myList.erase(iter);
    }
    Only problem is that since it returns the one AFTER, you get output like this:
    Code:
    $
    0
    1
    2
    3
    4
    5
    7
    8
    9
    0
    1
    2
    3
    4
    6
    7
    8
    9
    So 6 is skipped. So to balance it out with that of the for loop, you have to do this:

    Code:
    for (iter = myList.begin() ; iter != myList.end() ; ++iter)
    {
         std::cout << (*iter) << std::endl;
         if ((*iter) == 5)
         {
              iter = myList.erase(iter);
              iter--;
         }
    }
    To get desired results:
    Code:
    $
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    0
    1
    2
    3
    4
    6
    7
    8
    9
    Arg. That's just annoying...

    EDIT:
    Or this:
    Code:
    for (iter = myList.begin() ; iter != myList.end() ; ++iter)
    {
         std::cout << (*iter) << std::endl;
         if ((*iter) == 5)
              iter = myList.erase(iter)--;
    }
    Bit less retarded I guess...but still pretty bad...
    Last edited by Syndacate; 02-09-2011 at 04:41 PM.

  2. #2
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by Syndacate View Post
    Code:
    for (iter = myList.begin() ; iter != myList.end() ; ++iter)
    {
         std::cout << (*iter) << std::endl;
         if ((*iter) == 5)
         {
              iter = myList.erase(iter);
              iter--;
         }
    }
    Arg. That's just annoying...

    EDIT:
    Or this:
    Code:
    for (iter = myList.begin() ; iter != myList.end() ; ++iter)
    {
         std::cout << (*iter) << std::endl;
         if ((*iter) == 5)
              iter = myList.erase(iter)--;
    }
    Bit less retarded I guess...but still pretty bad...
    Both of those suggestions are broken, do not try to do that. You must simply remove any iterator incrementing from the last part of the for-loop expression (the ++iter) and only increment if not erasing.
    Otherwise:
    Code:
    iter = myList.erase(iter++);
    Last edited by iMalc; 02-09-2011 at 11:50 PM.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  3. #3
    Registered User
    Join Date
    Aug 2010
    Location
    Rochester, NY
    Posts
    196
    Quote Originally Posted by anon View Post
    Both those snippets have a big problem. If you happen to erase the first item in the container, decrementing the result (iterator to the new first item) will make the iterator go out of bounds ("previous" to myList.begin()).

    I've shown the classical way of doing this: only increment the iterator if you don't erase.
    Yeah, that's a good point, they both will become invalid on the first element. The remove() function only lends itself to this particular case, I suppose the remove_if() function would be complimentary as handy for determining when something is to be erased.

    Quote Originally Posted by iMalc View Post
    Both of those suggestions are broken, do not try to do that. You must simply remove any iterator incrementing from the last part of the for-loop expression (the ++iter) and only increment if not erasing.
    Otherwise:
    Code:
    iter = myList.erase(iter++);
    Wouldn't that expression erase element 5, then increment the now possibly invalid iterator, then set the iterator to the element after (6) ? In essence, doing nothing? I'm pretty sure the postfix increment operator has higher precedence than the assignment operator.

    Though regardless, I get the point of what you're doing. I guess remove/remove_if is a better for this type of situation unless you know ahead of time a particular value or range to remove from the list.

    Thanks guys.

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Wouldn't that expression erase element 5, then increment the now possibly invalid iterator, then set the iterator to the element after (6) ? In essence, doing nothing? I'm pretty sure the postfix increment operator has higher precedence than the assignment operator.
    That increment is pointless, since the value assigned to the left-hand side is the result of the function call anyway.

    Perhaps this was meant.

    Code:
    list.erase(iter++);
    This not incrementing an invalid iterator has to do with sequence points: side-effects have to be evaluated before entering the function body.

    BTW, whether this is a right thing to do or not depends on the container. E.g don't try this with a vector.

    If you want to erase elements from the entire list, then remove erases elements with a particular value and remove_if erases elements for which a condition is true. You'll only need a manual loop for a task more complicated, and I don't think there's much new to invent about how that looks.
    Last edited by anon; 02-10-2011 at 06:53 AM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  5. #5
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by anon View Post
    Perhaps this was meant.

    Code:
    list.erase(iter++);
    Yes indeed. Copy and paste error on my part.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  6. #6
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    since this is going on..i don't still understand why I can't just increment the iterator after erasing it..i really get the point of the else

    if erase returns the element after the element to be deleted in question(in this case 5..so it should return the address that points to 6, right)..in the if statement i should be able to do..

    Code:
         while(iter!=list.end())
         {
             if(*iter==5)
            {
                 iter = list.erase(iter) ;
                 cout << *iter ;
            }
    
            iter++ ;
            cout << *iter ;
         }
    If I do that I get a seg fault...I don't get it..that should be perfectly safe..And I've been reading that a list is sequential in memory..i even printed it out myself..and the addresses using the STL list template are freaking sequential..so why do I get a access violation, when I try that?
    You ended that sentence with a preposition...Bastard!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Unknown memory leak with linked lists...
    By RaDeuX in forum C Programming
    Replies: 6
    Last Post: 12-07-2008, 04:09 AM
  2. instantiated from here: errors...
    By advocation in forum C++ Programming
    Replies: 5
    Last Post: 03-27-2005, 09:01 AM
  3. How can I traverse a huffman tree
    By carrja99 in forum C++ Programming
    Replies: 3
    Last Post: 04-28-2003, 05:46 PM
  4. List class
    By SilasP in forum C++ Programming
    Replies: 0
    Last Post: 02-10-2002, 05:20 PM
  5. singly linked list
    By clarinetster in forum C Programming
    Replies: 2
    Last Post: 08-26-2001, 10:21 PM