set<>::erase(iterator) question

  • Follow


Usually STL containers have something like "iterator 
container<>::erase(iterator)" which erases the element the iterator points 
to and returns another valid iterator. Set does not have this, set::erase() 
returns void and "invalidates" the iterator.

Now I have the following code:

while(!some_set.empty()) {
for(it = some_set.begin(); it != some_set.end(); it++)
{
        ...
        if (something == true) some_set.erase(it);
        ...
}
}

And it always worked (using GCC3.2). Now running the same program using the 
same test data on another machine (GCC3.3) it is caught in an endless loop.
What could be going on here?

0
Reply harald.grossauer (25) 9/23/2003 4:07:54 PM

Harald Grossauer wrote:
> Usually STL containers have something like "iterator
> container<>::erase(iterator)" which erases the element the iterator
> points to and returns another valid iterator. Set does not have this,
> set::erase() returns void and "invalidates" the iterator.
[SNIP]

Get Effective STL from Scott Meyers.

// This is not necessary: while(!some_set.empty()) {
for(it = some_set.begin(); it != some_set.end(); ) // Change
{
  ...
  if (something == true) some_set.erase(it++);  // Change
  else ++it; // Change
  ...
}

You need to get the valid iterator *before* the erase runs.

-- 
WW aka Attila


0
Reply wolof (743) 9/23/2003 4:15:53 PM


"Harald Grossauer" <harald.grossauer@uibk.ac.at> wrote in message news:3f706fb1@sia.uibk.ac.at...
> Usually STL containers have something like "iterator
> container<>::erase(iterator)" which erases the element the iterator points
> to and returns another valid iterator.

That's true for sequences.

> Set does not have this, set::erase()  returns void and "invalidates" the iterator.

That's the way associative containers are, unfortuantely.   However, the nice thing
is that they only invalidate the erased iterator.

> for(it = some_set.begin(); it != some_set.end(); it++)
> {
>         ...
>         if (something == true) some_set.erase(it);
>         ...
> }
You have two chocies:
    1.  remember the next iterator somewhere
    2.  use post increment to accomplish the same thing

    next_it = it+1;
    if(something == true) some_set.erase(it);
    it = next_it;

or
    if(something == true) some_set.erase(it++);
    else ++it;


0
Reply ron156 (1434) 9/23/2003 4:17:42 PM

WW wrote in <bkprlo$fg3$1@phys-news1.kolumbus.fi>:

> Harald Grossauer wrote:
>> Usually STL containers have something like "iterator
>> container<>::erase(iterator)" which erases the element the iterator
>> points to and returns another valid iterator. Set does not have this,
>> set::erase() returns void and "invalidates" the iterator.
> [SNIP]
> 
> Get Effective STL from Scott Meyers.
> 
> // This is not necessary: while(!some_set.empty()) {
> for(it = some_set.begin(); it != some_set.end(); ) // Change
> {
>   ...
>   if (something == true) some_set.erase(it++);  // Change
>   else ++it; // Change
>   ...
> }
> 
> You need to get the valid iterator *before* the erase runs.

if i'm not mistaken erase returns the next valid iterator, so:

> for(it = some_set.begin(); it != some_set.end(); ) // Change
> {
>   ...
    if (something == true) 
        it = some_set.erase(it++);
    ...
> }

should do the trick?

-- 
Groeten keanu,
 Jabber ID: knu[at]amessage[dot]de 
 GPG Key-ID: 0x3246DE81
0
Reply usenet90 (7) 9/23/2003 6:10:47 PM

"keanu" <usenet@keanu.be> wrote in message news:H00cb.36204$_q1.1687695@phobos.telenet-ops.be...

> if i'm not mistaken erase returns the next valid iterator, so:

Yoiu are mistaken.   Did you even read the original post?   The erase on
associative containers do not, unfortunately, return anything.

>
> > for(it = some_set.begin(); it != some_set.end(); ) // Change
> > {
> >   ...
>     if (something == true)
>         it = some_set.erase(it++);
>     ...
> > }

That won't even work on containers where erase DOES return something.   It's
undefined behavior in that case.   You can do on sequences

    if(something)
        it = some_sequence.erase(it);
    else ++it;

or on associative containers
    if(something)
        some_set(it++);
    else ++it;


0
Reply ron156 (1434) 9/23/2003 6:43:49 PM

keanu wrote:

> 
> if i'm not mistaken erase returns the next valid iterator, so:

Not for associative containers. That's sort of the point of the thread.

-Kevin
-- 
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

0
Reply usenet1.spamfree.fusion (961) 9/23/2003 6:48:19 PM

Ron Natalie wrote:

> 
>>>for(it = some_set.begin(); it != some_set.end(); ) // Change
>>>{
>>>  ...
>>
>>    if (something == true)
>>        it = some_set.erase(it++);
>>    ...
>>
>>>}
> 
> 
> That won't even work on containers where erase DOES return something.   It's
> undefined behavior in that case.

Why is it undefined behavior? The increment is 'finished' before the 
function call (sequence point immediately before a function call) and 
the assignment occurs after, right?

-Kevin
-- 
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

0
Reply usenet1.spamfree.fusion (961) 9/23/2003 6:57:48 PM

> That won't even work on containers where erase DOES return something.  
> It's
> undefined behavior in that case.   You can do on sequences
> 
>     if(something)
>         it = some_sequence.erase(it);
>     else ++it;

this is what i meant, the ++ was a left over from the copy paste + no sleep

for some reason i thought erase returns the next iterator for every
container

0
Reply usenet90 (7) 9/23/2003 7:02:09 PM

"Kevin Goodsell" <usenet1.spamfree.fusion@neverbox.com> wrote in message news:MI0cb.858$RW4.72@newsread4.news.pas.earthlink.net...

> >>        it = some_set.erase(it++);

>
> Why is it undefined behavior? The increment is 'finished' before the
> function call (sequence point immediately before a function call) and
> the assignment occurs after, right?

Yeah, I guess you're right.   I was thinking that the side effect could be delayed
but there is an inherent sequence point after the function args are evaluated and
again on return.


0
Reply ron156 (1434) 9/23/2003 7:06:33 PM

Ron Natalie wrote:


> You have two chocies:
>     1.  remember the next iterator somewhere
>     2.  use post increment to accomplish the same thing
> 
>     next_it = it+1;
>     if(something == true) some_set.erase(it);
>     it = next_it;

That's how I did it then. I just thought there might be a "nicer" version 
without introducing another "dummy iterator".

> 
> or
>     if(something == true) some_set.erase(it++);
>     else ++it;

0
Reply harald.grossauer (25) 9/24/2003 7:31:35 AM

9 Replies
37 Views

(page loaded in 0.124 seconds)


Reply: