Erasing map elements by iterator

Discussion in 'C++' started by Owen Brydon, Oct 15, 2003.

  1. Owen Brydon

    Owen Brydon Guest

    Hi,

    Is the following code legal? g++ 3.2 barfs on it, although it seems
    fine to me.

    #include <map>

    using std::map;

    int main()
    {
    map<int,int> i;
    i[0]=6;
    i[54]=2;
    map<int,int>::iterator it=i.begin();
    while(it!=i.end())
    {
    if(it->first==0) it=i.erase(it);
    else it++;
    }
    return 0;

    }

    The error message from g++ is:
    tmp.cpp:13: no match for `std::_Rb_tree_iterator<std::pair<const int,
    int>,
    std::pair<const int, int>&, std::pair<const int, int>*>& = void'
    operator
    /usr/include/c++/3.2/bits/stl_tree.h:184: candidates are:
    std::_Rb_tree_iterator<std::pair<const int, int>, std::pair<const
    int,
    int>&, std::pair<const int, int>*>&
    std::_Rb_tree_iterator<std::pair<const
    int, int>, std::pair<const int, int>&, std::pair<const int,
    int>*>::eek:perator=(const std::_Rb_tree_iterator<std::pair<const int,
    int>,
    std::pair<const int, int>&, std::pair<const int, int>*>&)


    As a workaround, is it valid to do the following, or does erasing the
    iterator 'tmp' from the map (below) render the iterator 'it' invalid?
    #include <map>

    using std::map;

    int main()
    {
    map<int,int> i;
    i[0]=6;
    i[54]=2;
    map<int,int>::iterator it=i.begin();
    while(it!=i.end())
    {
    if(it->first==0)
    {
    map<int,int>::iterator tmp=it;
    it++;
    i.erase(tmp);
    }
    else it++;
    }
    return 0;

    }

    Regards,

    Owen Brydon
    Owen Brydon, Oct 15, 2003
    #1
    1. Advertising

  2. Owen Brydon

    Ron Natalie Guest

    "Owen Brydon" <> wrote in message news:...

    > Is the following code legal? g++ 3.2 barfs on it, although it seems
    > fine to me.


    It's not.

    > if(it->first==0) it=i.erase(it);


    map::erase returns void.

    if(it->first == 0) it.erase(it++);
    else ++it;
    Ron Natalie, Oct 15, 2003
    #2
    1. Advertising

  3. Owen Brydon wrote:
    > Hi,
    >
    > Is the following code legal? g++ 3.2 barfs on it, although it seems
    > fine to me.
    >
    > #include <map>
    >
    > using std::map;
    >
    > int main()
    > {
    > map<int,int> i;
    > i[0]=6;
    > i[54]=2;
    > map<int,int>::iterator it=i.begin();
    > while(it!=i.end())
    > {
    > if(it->first==0) it=i.erase(it);

    map::erase returns void

    > else it++;
    > }
    > return 0;
    >
    > }
    >
    > The error message from g++ is:
    > tmp.cpp:13: no match for `std::_Rb_tree_iterator<std::pair<const int,
    > int>,
    > std::pair<const int, int>&, std::pair<const int, int>*>& = void'
    > operator


    gcc complains it can't find a void assignment ....

    >
    > As a workaround, is it valid to do the following, or does erasing the
    > iterator 'tmp' from the map (below) render the iterator 'it' invalid?


    The code is fine and likely the only way to do it. A map iterator
    remains valid for the life of the map entry.
    Gianni Mariani, Oct 15, 2003
    #3
  4. Owen Brydon

    Owen Brydon Guest

    Ron Natalie wrote:
    > "Owen Brydon" <> wrote in message
    > news:...
    >
    >
    >> Is the following code legal? g++ 3.2 barfs on it, although it seems
    >> fine to me.

    >
    >
    > It's not.
    >
    >> if(it->first==0) it=i.erase(it);

    >

    It seems not :)
    In this case,
    http://www.dinkumware.com/manuals/reader.aspx?b=p/&h=map.html is
    incorrect, which is where I got the notion that it returned an iterator.


    > map::erase returns void.
    >
    > if(it->first == 0) it.erase(it++); else ++it;
    >


    Is this 100% safe? Is the iterator it valid for postincrement after
    being erased from the map?

    Is the other example I gave where the iterator is copied, then
    incremented, then the copy is erased, 100% safe?

    Regards,

    Owen Brydon
    Owen Brydon, Oct 15, 2003
    #4
  5. Owen Brydon

    Guest

    On Wed, 15 Oct 2003 18:52:30 +0100, Owen Brydon <> wrote:

    > Ron Natalie wrote:
    >> "Owen Brydon" <> wrote in message
    >> news:...
    >>
    >>
    >>> Is the following code legal? g++ 3.2 barfs on it, although it seems
    >>> fine to me.

    >>
    >>
    >> It's not.
    >>
    >>> if(it->first==0) it=i.erase(it);

    >>

    > It seems not :)
    > In this case,
    > http://www.dinkumware.com/manuals/reader.aspx?b=p/&h=map.html is
    > incorrect, which is where I got the notion that it returned an iterator.


    map erase(const key_type&) returns size_type

    >
    >
    >> map::erase returns void.
    >>
    >> if(it->first == 0) it.erase(it++); else ++it;
    >>

    >
    > Is this 100% safe? Is the iterator it valid for postincrement after being
    > erased from the map?


    erase has an iterator argument, postincrement operator ++ applied to map
    iterator returns copy of current iterator and increments current iterator.

    >
    > Is the other example I gave where the iterator is copied, then
    > incremented, then the copy is erased, 100% safe?


    Yes,it is, as well as the shorter version above which does the same.

    >
    > Regards,
    >
    > Owen Brydon
    >
    >




    --
    grzegorz
    , Oct 15, 2003
    #5
  6. >> map::erase returns void.
    >> if(it->first == 0) it.erase(it++); else ++it;


    Owen> Is this 100% safe? Is the iterator it valid for postincrement after
    Owen> being erased from the map?

    The example has a typographical error: it.erase(it++) should be
    i.erase(it++). With that change, the example is 100% safe:
    Although it skates right up to the edge of the broken ice, it
    avoids drowning in the frigid water.

    The key is that there is a sequence point between evaluating a
    function's arguments and calling the function, which means that
    before i.erase is called, the value of it has already been
    incremented. Therefore, it is no longer referring to the element
    that is about to be deleted, and its value therefore remains valid.

    --
    Andrew Koenig,
    Andrew Koenig, Oct 16, 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. Generic Usenet Account
    Replies:
    8
    Views:
    391
    Generic Usenet Account
    Jan 3, 2004
  2. Replies:
    3
    Views:
    400
    Vyacheslav Kononenko
    Jan 10, 2005
  3. Tescobar
    Replies:
    12
    Views:
    484
    Vyacheslav Kononenko
    Jul 25, 2005
  4. Jim Langston
    Replies:
    8
    Views:
    452
    Mark P
    May 30, 2006
  5. Erasing From a map

    , Mar 28, 2007, in forum: C++
    Replies:
    4
    Views:
    314
    Michael Oswald
    Mar 29, 2007
Loading...

Share This Page