How to delete stl<map> element from iterator?

Discussion in 'C++' started by Steve Edwards, Feb 21, 2006.

  1. Hi,

    After making an iterator to a map and stepping through a loop, I want to
    delete any entries that satisfy a test from an external function.

    MyMapType::const_iterator iter;

    for(iter = m->begin(); iter != m->end(); ++iter)
    {
    a = iter->first;
    b = iter->second;
    if ( Test(a,b) == true)
    iter->delete?();
    }

    How do I actually delete the element that iter is pointing to?

    Thanks

    Steve
    Steve Edwards, Feb 21, 2006
    #1
    1. Advertising

  2. Steve Edwards

    Mike Wahler Guest

    "Steve Edwards" <> wrote in message
    news:...
    > Hi,
    >
    > After making an iterator to a map and stepping through a loop, I want to
    > delete any entries that satisfy a test from an external function.
    >
    > MyMapType::const_iterator iter;
    >
    > for(iter = m->begin(); iter != m->end(); ++iter)


    This assumes that 'm' is the name of a pointer to your map,
    not of the map itself. I'll keep that assumption below.

    > {
    > a = iter->first;
    > b = iter->second;
    > if ( Test(a,b) == true)
    > iter->delete?();
    > }
    >
    > How do I actually delete the element that iter is pointing to?


    for(iter = m->begin(); iter != m->end(); ++iter)
    {
    if(condition)
    iter = m->erase(iter);
    }


    An excellent reference for the C++ standard library:
    www.josuttis.com/libbook

    -Mike
    Mike Wahler, Feb 21, 2006
    #2
    1. Advertising

  3. Steve Edwards wrote:
    > After making an iterator to a map and stepping through a loop, I want to
    > delete any entries that satisfy a test from an external function.
    >
    > MyMapType::const_iterator iter;
    >
    > for(iter = m->begin(); iter != m->end(); ++iter)
    > {
    > a = iter->first;
    > b = iter->second;
    > if ( Test(a,b) == true)
    > iter->delete?();
    > }
    >
    > How do I actually delete the element that iter is pointing to?


    You ask your map to erase it.

    Something like

    m->erase(iter);

    Beware, though, that after erasing the 'iter' becomes invalid. You cannot
    increment it after that. You might want to rewrite your loop like this:

    for (.... ; ) // no increment at the end
    {
    a =
    b =
    if (..
    m->erase(iter++);
    else
    ++iter;
    }

    V
    --
    Please remove capital As from my address when replying by mail
    Victor Bazarov, Feb 21, 2006
    #3
  4. Mike Wahler wrote:
    > if(condition)
    > iter = m->erase(iter);


    IIRC, 'map::erase' has 'void' return type. Some Standard Library
    implementations actually violate that to be consistent with other
    (sequential) containers, and probably justifiedly, but generally
    speaking your code is ill-formed.

    > }
    >
    >
    > An excellent reference for the C++ standard library:
    > www.josuttis.com/libbook


    Yep. Check out table 6.31 in it.

    V
    --
    Please remove capital As from my address when replying by mail
    Victor Bazarov, Feb 21, 2006
    #4
  5. Steve Edwards

    Mike Wahler Guest

    "Victor Bazarov" <> wrote in message
    news:mrIKf.1333$01.us.to.verio.net...
    > Steve Edwards wrote:


    >> How do I actually delete the element that iter is pointing to?

    >
    > You ask your map to erase it.
    >
    > Something like
    >
    > m->erase(iter);
    >
    > Beware, though, that after erasing the 'iter' becomes invalid. You cannot
    > increment it after that. You might want to rewrite your loop like this:


    Well, I think we both botched our replies. I forgot the
    'else' part, and yours disregards the invalid iterator. :)

    >
    > for (.... ; ) // no increment at the end
    > {
    > a =
    > b =
    > if (..
    > m->erase(iter++);


    iter = m->erase(iter);

    > else
    > ++iter;
    > }


    -Mike
    Mike Wahler, Feb 21, 2006
    #5
  6. Mike Wahler wrote:
    > "Victor Bazarov" <> wrote in message
    > news:mrIKf.1333$01.us.to.verio.net...
    >
    >>Steve Edwards wrote:

    >
    >
    >>>How do I actually delete the element that iter is pointing to?

    >>
    >>You ask your map to erase it.
    >>
    >>Something like
    >>
    >> m->erase(iter);
    >>
    >>Beware, though, that after erasing the 'iter' becomes invalid. You cannot
    >>increment it after that. You might want to rewrite your loop like this:

    >
    >
    > Well, I think we both botched our replies. I forgot the
    > 'else' part, and yours disregards the invalid iterator. :)


    Think again.

    >
    >
    >> for (.... ; ) // no increment at the end
    >> {
    >> a =
    >> b =
    >> if (..
    >> m->erase(iter++);

    >
    >
    > iter = m->erase(iter);
    >
    >
    >> else
    >> ++iter;
    >> }

    >
    >
    > -Mike
    >
    >



    --
    Please remove capital As from my address when replying by mail
    Victor Bazarov, Feb 21, 2006
    #6

  7. >
    > Beware, though, that after erasing the 'iter' becomes invalid. You cannot
    > increment it after that. You might want to rewrite your loop like this:
    >
    > for (.... ; ) // no increment at the end
    > {
    > a =
    > b =
    > if (..
    > m->erase(iter++);
    > else
    > ++iter;
    > }
    >
    > V


    Thanks, but sorry, I don't quite understand. If you say the iterator
    becomes invalid, should I break at that point. (in which case I haven't
    processed all my elements yet.)
    On the other hand, I can't continue if the iterator's invalid, can I?

    Steve
    Steve Edwards, Feb 21, 2006
    #7
  8. In article <0mIKf.2502$>,
    "Mike Wahler" <> wrote:

    > "Steve Edwards" <> wrote in message
    > news:...
    > > Hi,
    > >
    > > After making an iterator to a map and stepping through a loop, I want to
    > > delete any entries that satisfy a test from an external function.
    > >
    > > MyMapType::const_iterator iter;
    > >
    > > for(iter = m->begin(); iter != m->end(); ++iter)

    >
    > This assumes that 'm' is the name of a pointer to your map,
    > not of the map itself. I'll keep that assumption below.
    >
    > > {
    > > a = iter->first;
    > > b = iter->second;
    > > if ( Test(a,b) == true)
    > > iter->delete?();
    > > }
    > >
    > > How do I actually delete the element that iter is pointing to?

    >
    > for(iter = m->begin(); iter != m->end(); ++iter)
    > {
    > if(condition)
    > iter = m->erase(iter);
    > }
    >
    >
    > An excellent reference for the C++ standard library:
    > www.josuttis.com/libbook
    >
    > -Mike




    Thanks for the link, it's just what I need.

    My compiler is complaining about "iter = m->erase(iter);"

    (error: no match for 'operator = ')
    Steve Edwards, Feb 21, 2006
    #8
  9. Steve Edwards

    TB Guest

    Steve Edwards skrev:
    >> Beware, though, that after erasing the 'iter' becomes invalid. You cannot
    >> increment it after that. You might want to rewrite your loop like this:
    >>
    >> for (.... ; ) // no increment at the end
    >> {
    >> a =
    >> b =
    >> if (..
    >> m->erase(iter++);
    >> else
    >> ++iter;
    >> }
    >>
    >> V

    >
    > Thanks, but sorry, I don't quite understand. If you say the iterator
    > becomes invalid, should I break at that point. (in which case I haven't
    > processed all my elements yet.)
    > On the other hand, I can't continue if the iterator's invalid, can I?
    >


    The statement:

    iter++;

    increments the iterator and returns the previous position. Compare with

    int x = 8, y = 0;
    y = x++;
    // y = 8, x == 9

    so the following

    m->erase(iter++);

    safely erases the desired element and retains a valid iterator pointing
    to the next element or m->end().

    --
    TB @ SWEDEN
    TB, Feb 21, 2006
    #9
  10. Steve Edwards wrote:
    >>Beware, though, that after erasing the 'iter' becomes invalid. You cannot
    >>increment it after that. You might want to rewrite your loop like this:
    >>
    >> for (.... ; ) // no increment at the end
    >> {
    >> a =
    >> b =
    >> if (..
    >> m->erase(iter++);
    >> else
    >> ++iter;
    >> }
    >>
    >>V

    >
    >
    > Thanks, but sorry, I don't quite understand. If you say the iterator
    > becomes invalid, should I break at that point. (in which case I haven't
    > processed all my elements yet.)


    Why should you? By passing the value of the post-incremented iterator you
    keep it valid. If the 'iter' isn't post-incremented, after 'erase' does
    its job, 'iter' cannot be used -- it's invalid. In the proposed code, the
    value of 'iter' is passed to 'erase', but _outside_ the object 'iter' is
    already pointing to the next element of the map, and therefore is OK.

    > On the other hand, I can't continue if the iterator's invalid, can I?


    No, if it's invalid, you can't. The whole point of using post-increment
    is to keep it valid.

    V
    --
    Please remove capital As from my address when replying by mail
    Victor Bazarov, Feb 21, 2006
    #10
  11. Steve Edwards wrote:
    > In article <0mIKf.2502$>,
    > "Mike Wahler" <> wrote:
    >>"Steve Edwards" <> wrote in message
    >>news:...
    >> [..]
    >>>How do I actually delete the element that iter is pointing to?

    >>
    >>for(iter = m->begin(); iter != m->end(); ++iter)
    >>{
    >> if(condition)
    >> iter = m->erase(iter);
    >>}
    >> [..]

    >
    > My compiler is complaining about "iter = m->erase(iter);"


    Of course it does. 'm->erase(iter)' returns 'void'. Mike was too hasty
    to suggest that solution. It would work for a 'list', for example. It
    just doesn't work for 'map'.

    V
    --
    Please remove capital As from my address when replying by mail
    Victor Bazarov, Feb 21, 2006
    #11
  12. Steve Edwards

    Mike Wahler Guest

    "Victor Bazarov" <> wrote in message
    news:VJIKf.1336$01.us.to.verio.net...
    > Mike Wahler wrote:
    >> "Victor Bazarov" <> wrote in message
    >> news:mrIKf.1333$01.us.to.verio.net...
    >>
    >>>Steve Edwards wrote:

    >>
    >>
    >>>>How do I actually delete the element that iter is pointing to?
    >>>
    >>>You ask your map to erase it.
    >>>
    >>>Something like
    >>>
    >>> m->erase(iter);
    >>>
    >>>Beware, though, that after erasing the 'iter' becomes invalid. You
    >>>cannot
    >>>increment it after that. You might want to rewrite your loop like this:

    >>
    >>
    >> Well, I think we both botched our replies. I forgot the
    >> 'else' part, and yours disregards the invalid iterator. :)

    >
    > Think again.


    OK I did. I see I wasn't thinking before. :)

    >
    >>
    >>
    >>> for (.... ; ) // no increment at the end
    >>> {
    >>> a =
    >>> b =
    >>> if (..
    >>> m->erase(iter++);

    >>
    >>
    >> iter = m->erase(iter);


    You've already pointed out my error with this line elsethread.

    My excuse is ... we've got a new dog, she ate my attention. :)

    -Mike
    Mike Wahler, Feb 23, 2006
    #12
    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. rg
    Replies:
    1
    Views:
    2,147
    tom_usenet
    Jul 22, 2004
  2. wolverine
    Replies:
    3
    Views:
    1,065
    Chris
    Jul 31, 2006
  3. cppquest
    Replies:
    5
    Views:
    366
    Dana Good
    Feb 22, 2007
  4. zl2k
    Replies:
    27
    Views:
    1,575
    Francesco S. Carta
    Sep 7, 2010
  5. Jim Anderson

    problem with iterator (map iterator)

    Jim Anderson, Jan 10, 2014, in forum: C++
    Replies:
    3
    Views:
    121
    Luca Risolia
    Jan 13, 2014
Loading...

Share This Page