Connecting Tech Pros Worldwide Forums | Help | Site Map

STL std::map erase

Pieter Thysebaert
Guest
 
Posts: n/a
#1: Jul 22 '05


Hello,

I've got a question conerning erasing key-value pairs from a std::map while
iterating over it.

According to the STL docs, erasing an element in a map invalidates all
iterators pointing to that element

so

for (map<...>::iterator i = mymap.begin(); i != mymap.end(); i++) {
if (test(i)) {
mymap.erase(i);
mymap.insert(newelement);
}
}

looks like bad practice, and it does crash when it gets executed, at least
on one machine i've run such code on.

So my question is, how do I conveniently erase the "current" element in a
map on the fly while I'm iterating over it? (I admit that this sounds as
weird in English as it sounds in C++)?

Thanx,

Pieter


Karl Heinz Buchegger
Guest
 
Posts: n/a
#2: Jul 22 '05

re: STL std::map erase


Pieter Thysebaert wrote:[color=blue]
>
> Hello,
>
> I've got a question conerning erasing key-value pairs from a std::map while
> iterating over it.
>
> According to the STL docs, erasing an element in a map invalidates all
> iterators pointing to that element
>
> so
>
> for (map<...>::iterator i = mymap.begin(); i != mymap.end(); i++) {
> if (test(i)) {
> mymap.erase(i);
> mymap.insert(newelement);
> }
> }
>
> looks like bad practice, and it does crash when it gets executed, at least
> on one machine i've run such code on.
>
> So my question is, how do I conveniently erase the "current" element in a
> map on the fly while I'm iterating over it? (I admit that this sounds as
> weird in English as it sounds in C++)?[/color]

So what is the real problem?
The problem is, that after erasing the element with iterator i, you need
that iterator again, for the increment, to get at the next map element.
As you know this is not valid. So a possible solution is: get your hands
at an iterator for the next element, *before* you do the erase.

--
Karl Heinz Buchegger
kbuchegg@gascad.at
John Harrison
Guest
 
Posts: n/a
#3: Jul 22 '05

re: STL std::map erase



"Pieter Thysebaert" <pieter.thysebaert@toorug.muchac.spambe> wrote in
message news:c8010s$a5l$1@gaudi2.UGent.be...[color=blue]
>
>
> Hello,
>
> I've got a question conerning erasing key-value pairs from a std::map[/color]
while[color=blue]
> iterating over it.
>
> According to the STL docs, erasing an element in a map invalidates all
> iterators pointing to that element
>
> so
>
> for (map<...>::iterator i = mymap.begin(); i != mymap.end(); i++) {
> if (test(i)) {
> mymap.erase(i);
> mymap.insert(newelement);
> }
> }
>
> looks like bad practice, and it does crash when it gets executed, at least
> on one machine i've run such code on.
>
> So my question is, how do I conveniently erase the "current" element in a
> map on the fly while I'm iterating over it? (I admit that this sounds as
> weird in English as it sounds in C++)?[/color]

for (map<...>::iterator i = mymap.begin(); i != mymap.end(); ) {
if (test(i)) {
mymap.erase(i++);
mymap.insert(newelement);
} else {
++i;
}
}

Understanding this code requires a proper understanding of how 'i++' works.

john


Howard
Guest
 
Posts: n/a
#4: Jul 22 '05

re: STL std::map erase



"John Harrison" <john_andronicus@hotmail.com> wrote in message
news:2ghjh6F2s3b7U1@uni-> >[color=blue][color=green]
> > So my question is, how do I conveniently erase the "current" element in[/color][/color]
a[color=blue][color=green]
> > map on the fly while I'm iterating over it? (I admit that this sounds as
> > weird in English as it sounds in C++)?[/color]
>
> for (map<...>::iterator i = mymap.begin(); i != mymap.end(); ) {
> if (test(i)) {
> mymap.erase(i++);
> mymap.insert(newelement);
> } else {
> ++i;
> }
> }
>
> Understanding this code requires a proper understanding of how 'i++'[/color]
works.

Ok...so how about an explanation?

I don't see how this is any different. When the call to erase finishes, all
iterators pointing to that element are no longer valid. And isn't an
implementation allowed to wait until the erase call returns, and then
perform that increment? In that case, i cannot be incremented because it is
invalid already, right? For such an implementation, incrementing i in the
function parameter ought to be the same as incrementing it in the for
statement, as far as I can see.

Can't an implementation create identical code for both these cases?...

foo(i++);

vs.

f(i);
i++;

I could see that the implementation might not be *required* to make those
the same, but would it not be *allowed* to make them the same?

What am I missing here?

-Howard


John Harrison
Guest
 
Posts: n/a
#5: Jul 22 '05

re: STL std::map erase



"Howard" <alicebt@hotmail.com> wrote in message
news:7cNoc.51315$Ut1.1426660@bgtnsc05-news.ops.worldnet.att.net...[color=blue]
>
> "John Harrison" <john_andronicus@hotmail.com> wrote in message
> news:2ghjh6F2s3b7U1@uni-> >[color=green][color=darkred]
> > > So my question is, how do I conveniently erase the "current" element[/color][/color][/color]
in[color=blue]
> a[color=green][color=darkred]
> > > map on the fly while I'm iterating over it? (I admit that this sounds[/color][/color][/color]
as[color=blue][color=green][color=darkred]
> > > weird in English as it sounds in C++)?[/color]
> >
> > for (map<...>::iterator i = mymap.begin(); i != mymap.end(); ) {
> > if (test(i)) {
> > mymap.erase(i++);
> > mymap.insert(newelement);
> > } else {
> > ++i;
> > }
> > }
> >
> > Understanding this code requires a proper understanding of how 'i++'[/color]
> works.
>
> Ok...so how about an explanation?
>
> I don't see how this is any different. When the call to erase finishes,[/color]
all[color=blue]
> iterators pointing to that element are no longer valid. And isn't an
> implementation allowed to wait until the erase call returns, and then
> perform that increment?[/color]

No, that's exactly the point. i++ is a function call, and that function must
happen before the call to erase. The function call returns the 'old' value
of the iterator (that gets passed to erase), and increments the iterator to
its 'new' value as a side effect. All this must happen before erase is
called.

john


Howard
Guest
 
Posts: n/a
#6: Jul 22 '05

re: STL std::map erase



"John Harrison" <john_andronicus@hotmail.com> wrote in message
news:2ghlqlF2o863U1@uni-berlin.de...[color=blue]
>
> "Howard" <alicebt@hotmail.com> wrote in message
> news:7cNoc.51315$Ut1.1426660@bgtnsc05-news.ops.worldnet.att.net...[color=green]
> >
> > "John Harrison" <john_andronicus@hotmail.com> wrote in message
> > news:2ghjh6F2s3b7U1@uni-> >[color=darkred]
> > > > So my question is, how do I conveniently erase the "current" element[/color][/color]
> in[color=green]
> > a[color=darkred]
> > > > map on the fly while I'm iterating over it? (I admit that this[/color][/color][/color]
sounds[color=blue]
> as[color=green][color=darkred]
> > > > weird in English as it sounds in C++)?
> > >
> > > for (map<...>::iterator i = mymap.begin(); i != mymap.end(); ) {
> > > if (test(i)) {
> > > mymap.erase(i++);
> > > mymap.insert(newelement);
> > > } else {
> > > ++i;
> > > }
> > > }
> > >
> > > Understanding this code requires a proper understanding of how 'i++'[/color]
> > works.
> >
> > Ok...so how about an explanation?
> >
> > I don't see how this is any different. When the call to erase finishes,[/color]
> all[color=green]
> > iterators pointing to that element are no longer valid. And isn't an
> > implementation allowed to wait until the erase call returns, and then
> > perform that increment?[/color]
>
> No, that's exactly the point. i++ is a function call, and that function[/color]
must[color=blue]
> happen before the call to erase. The function call returns the 'old' value
> of the iterator (that gets passed to erase), and increments the iterator[/color]
to[color=blue]
> its 'new' value as a side effect. All this must happen before erase is
> called.
>
> john[/color]

Ahah! I understand now. Somehow I keep forgetting that ++ is actually a
function call (operator ++()). Thanks for the explanation.

-Howard


[color=blue]
>
>[/color]


Karl Heinz Buchegger
Guest
 
Posts: n/a
#7: Jul 22 '05

re: STL std::map erase


John Harrison wrote:[color=blue]
>
>
> No, that's exactly the point. i++ is a function call, and that function must
> happen before the call to erase.[/color]

Ahm.
Thats the wrong explanation.
The correct explanation is:
There is a sequence point immediatly after all arguments
to functions have been evaluated and just before the
function gets called.

So the compiler has no other choice: If there are side
effects during the evaluation of arguments, those side
effects have to be completed before the function gets
called.

That i++ in case of iterators is implemented as a function is
an implementation detail.

--
Karl Heinz Buchegger
kbuchegg@gascad.at
Karl Heinz Buchegger
Guest
 
Posts: n/a
#8: Jul 22 '05

re: STL std::map erase


Howard wrote:[color=blue]
>
>
> Ahah! I understand now. Somehow I keep forgetting that ++ is actually a
> function call (operator ++()).[/color]

It doens't matter.
Even if it were not, the increment has to happen before the
function actually gets called.


--
Karl Heinz Buchegger
kbuchegg@gascad.at
John Harrison
Guest
 
Posts: n/a
#9: Jul 22 '05

re: STL std::map erase



"Karl Heinz Buchegger" <kbuchegg@gascad.at> wrote in message
news:40A3AF85.8588CE71@gascad.at...[color=blue]
> John Harrison wrote:[color=green]
> >
> >
> > No, that's exactly the point. i++ is a function call, and that function[/color][/color]
must[color=blue][color=green]
> > happen before the call to erase.[/color]
>
> Ahm.
> Thats the wrong explanation.
> The correct explanation is:
> There is a sequence point immediatly after all arguments
> to functions have been evaluated and just before the
> function gets called.
>
> So the compiler has no other choice: If there are side
> effects during the evaluation of arguments, those side
> effects have to be completed before the function gets
> called.
>
> That i++ in case of iterators is implemented as a function is
> an implementation detail.
>[/color]


I wasn't completely sure if the same rules applied to ++ on a built in type,
fairly sure but not completely sure. So I tried to avoid saying 'its because
its a function call' and just gave a descriptive answer.

Thanks for the clarification.

john


Karl Heinz Buchegger
Guest
 
Posts: n/a
#10: Jul 22 '05

re: STL std::map erase


John Harrison wrote:[color=blue]
>
> "Karl Heinz Buchegger" <kbuchegg@gascad.at> wrote in message
> news:40A3AF85.8588CE71@gascad.at...[color=green]
> > John Harrison wrote:[color=darkred]
> > >
> > >
> > > No, that's exactly the point. i++ is a function call, and that function[/color][/color]
> must[color=green][color=darkred]
> > > happen before the call to erase.[/color]
> >
> > Ahm.
> > Thats the wrong explanation.
> > The correct explanation is:
> > There is a sequence point immediatly after all arguments
> > to functions have been evaluated and just before the
> > function gets called.
> >
> > So the compiler has no other choice: If there are side
> > effects during the evaluation of arguments, those side
> > effects have to be completed before the function gets
> > called.
> >
> > That i++ in case of iterators is implemented as a function is
> > an implementation detail.
> >[/color]
>
> I wasn't completely sure if the same rules applied to ++ on a built in type,[/color]

The ++ has nothing to do with it other then generating a side effect.

--
Karl Heinz Buchegger
kbuchegg@gascad.at
Howard
Guest
 
Posts: n/a
#11: Jul 22 '05

re: STL std::map erase



"Karl Heinz Buchegger" <kbuchegg@gascad.at> wrote in message
news:40A3B1AA.184C05DF@gascad.at...[color=blue]
> John Harrison wrote:[color=green]
> >
> > "Karl Heinz Buchegger" <kbuchegg@gascad.at> wrote in message
> > news:40A3AF85.8588CE71@gascad.at...[color=darkred]
> > > John Harrison wrote:
> > > >
> > > >
> > > > No, that's exactly the point. i++ is a function call, and that[/color][/color][/color]
function[color=blue][color=green]
> > must[color=darkred]
> > > > happen before the call to erase.
> > >
> > > Ahm.
> > > Thats the wrong explanation.
> > > The correct explanation is:
> > > There is a sequence point immediatly after all arguments
> > > to functions have been evaluated and just before the
> > > function gets called.
> > >
> > > So the compiler has no other choice: If there are side
> > > effects during the evaluation of arguments, those side
> > > effects have to be completed before the function gets
> > > called.
> > >
> > > That i++ in case of iterators is implemented as a function is
> > > an implementation detail.
> > >[/color]
> >
> > I wasn't completely sure if the same rules applied to ++ on a built in[/color][/color]
type,[color=blue]
>
> The ++ has nothing to do with it other then generating a side effect.
>
> --
> Karl Heinz Buchegger
> kbuchegg@gascad.at[/color]


So even if i were an int, it would still have to be incremented prior to
calling the function? That sure seems counter-intuitive to the notion of
"post-increment". Makes sense though, I guess.

Also, I guess that means that what is actually passed to the function is a
*copy* of the original iterator, since the original already has to point to
the next item, right?

This is very enlightening. It seems that I always have more to learn with
this language. Thanks...

-Howard







Andrey Tarasevich
Guest
 
Posts: n/a
#12: Jul 22 '05

re: STL std::map erase


Howard wrote:[color=blue]
> ...
> So even if i were an int, it would still have to be incremented prior to
> calling the function?[/color]

Yes.
[color=blue]
> That sure seems counter-intuitive to the notion of
> "post-increment". Makes sense though, I guess.[/color]

The function will still receive the original value of 'i'. That's why it
is called "post-increment".
[color=blue]
> Also, I guess that means that what is actually passed to the function is a
> *copy* of the original iterator, since the original already has to point to
> the next item, right?[/color]

Since this function receives its parameter "by value" - yes, it actually
receives a copy of the original iterator.

--
Best regards,
Andrey Tarasevich

Howard
Guest
 
Posts: n/a
#13: Jul 22 '05

re: STL std::map erase



"Andrey Tarasevich" <andreytarasevich@hotmail.com> wrote in message
news:10a7g29g28h2odf@news.supernews.com...[color=blue]
> Howard wrote:[color=green]
> > ...
> > So even if i were an int, it would still have to be incremented prior to
> > calling the function?[/color]
>
> Yes.
>[color=green]
> > That sure seems counter-intuitive to the notion of
> > "post-increment". Makes sense though, I guess.[/color]
>
> The function will still receive the original value of 'i'. That's why it
> is called "post-increment".
>[color=green]
> > Also, I guess that means that what is actually passed to the function is[/color][/color]
a[color=blue][color=green]
> > *copy* of the original iterator, since the original already has to point[/color][/color]
to[color=blue][color=green]
> > the next item, right?[/color]
>
> Since this function receives its parameter "by value" - yes, it actually
> receives a copy of the original iterator.
>[/color]

Ok...but then, what if you were to pass the iterator *by reference* to some
function instead? What value would the function then get, (considering the
previously stated rule that the increment side-effect has to be completed
prior to the calling of the function)? Would a temporary (un-incremented)
copy be created, passed by reference, and then that copy destroyed after the
return of the function? (That seems to be the only way to maintain the
concept of post-increment without violating the side-effect rule.)

-Howard





Julián Albo
Guest
 
Posts: n/a
#14: Jul 22 '05

re: STL std::map erase


Howard wrote:
[color=blue][color=green]
>> Since this function receives its parameter "by value" - yes, it actually
>> receives a copy of the original iterator.[/color]
>
> Ok...but then, what if you were to pass the iterator *by reference* to
> some
> function instead? What value would the function then get, (considering
> the previously stated rule that the increment side-effect has to be
> completed
> prior to the calling of the function)? Would a temporary (un-incremented)
> copy be created, passed by reference, and then that copy destroyed after
> the
> return of the function? (That seems to be the only way to maintain the
> concept of post-increment without violating the side-effect rule.)[/color]

That depends on how the iterator implements the pre and post ++ operators.
Habitually the post version returns a copy of the old value.

--
Salu2
joey tribbiani
Guest
 
Posts: n/a
#15: Jul 22 '05

re: STL std::map erase


Pieter Thysebaert wrote:[color=blue]
>
> Hello,[/color]
[color=blue]
> According to the STL docs, erasing an element in a map invalidates all
> iterators pointing to that element
>
> so
>
> for (map<...>::iterator i = mymap.begin(); i != mymap.end(); i++) {
> if (test(i)) {
> mymap.erase(i);
> mymap.insert(newelement);
> }
> }[/color]

Why not the following?

for (map<...>::iterator i = mymap.begin(); i != mymap.end(); i++) {
if (test(i)) {
i = mymap.erase(i);
}
}




Pete Becker
Guest
 
Posts: n/a
#16: Jul 22 '05

re: STL std::map erase


joey tribbiani wrote:[color=blue]
>
> Why not the following?
>
> for (map<...>::iterator i = mymap.begin(); i != mymap.end(); i++) {
> if (test(i)) {
> i = mymap.erase(i);
> }
> }[/color]

Because map::erase returns void according to the standard. Our
implementation returns an iterator, just like vector::erase. The next
version of the standard will probably make that change official.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jeff Flinn
Guest
 
Posts: n/a
#17: Jul 22 '05

re: STL std::map erase



"Pete Becker" <petebecker@acm.org> wrote in message
news:40A3D04A.8F9F43A9@acm.org...[color=blue]
> joey tribbiani wrote:[color=green]
> >
> > Why not the following?
> >
> > for (map<...>::iterator i = mymap.begin(); i != mymap.end(); i++) {
> > if (test(i)) {
> > i = mymap.erase(i);
> > }
> > }[/color]
>
> Because map::erase returns void according to the standard. Our
> implementation returns an iterator, just like vector::erase. The next
> version of the standard will probably make that change official.[/color]

Even with this extension/future std, the above is incorrect. 'i' will be
effectively incremented twice for each true 'test(i)'. 'i++' needs to be
moved from the for statement to an else clause.

Jeff F


joey tribbiani
Guest
 
Posts: n/a
#18: Jul 22 '05

re: STL std::map erase


Pete Becker wrote:
[color=blue]
> joey tribbiani wrote:
>[color=green]
>>Why not the following?
>>
>>for (map<...>::iterator i = mymap.begin(); i != mymap.end(); i++) {
>> if (test(i)) {
>> i = mymap.erase(i);
>> }
>>}[/color]
>
>
> Because map::erase returns void according to the standard. Our
> implementation returns an iterator, just like vector::erase. The next
> version of the standard will probably make that change official.
>[/color]
Oh, thanks, i didn't know - always thought you are the standard
(actually, never really thought about it)
Howard
Guest
 
Posts: n/a
#19: Jul 22 '05

re: STL std::map erase



"Pete Becker" <petebecker@acm.org> wrote in message
news:40A3D04A.8F9F43A9@acm.org...[color=blue]
> joey tribbiani wrote:[color=green]
> >
> > Why not the following?
> >
> > for (map<...>::iterator i = mymap.begin(); i != mymap.end(); i++) {
> > if (test(i)) {
> > i = mymap.erase(i);
> > }
> > }[/color]
>
> Because map::erase returns void according to the standard. Our
> implementation returns an iterator, just like vector::erase. The next
> version of the standard will probably make that change official.
>[/color]

Even if it *did* return an iterator, the above code would only work if it
returned an iterator to the *previous* item, because the for loop is going
to increment i every time. The implementation I'm using returns an iterator
to the *next* item (or to end(), if there are none beyond the given item).
In that case, it would have to be writtien:

for (map<...>::iterator i = mymap.begin(); i != mymap.end(); )
{
if (test(i))
i = mymap.erase(i);
else
i++;
}

-Howard


Pete Becker
Guest
 
Posts: n/a
#20: Jul 22 '05

re: STL std::map erase


Jeff Flinn wrote:[color=blue]
>
> "Pete Becker" <petebecker@acm.org> wrote in message
> news:40A3D04A.8F9F43A9@acm.org...[color=green]
> > joey tribbiani wrote:[color=darkred]
> > >
> > > Why not the following?
> > >
> > > for (map<...>::iterator i = mymap.begin(); i != mymap.end(); i++) {
> > > if (test(i)) {
> > > i = mymap.erase(i);
> > > }
> > > }[/color]
> >
> > Because map::erase returns void according to the standard. Our
> > implementation returns an iterator, just like vector::erase. The next
> > version of the standard will probably make that change official.[/color]
>
> Even with this extension/future std, the above is incorrect. 'i' will be
> effectively incremented twice for each true 'test(i)'. 'i++' needs to be
> moved from the for statement to an else clause.
>[/color]

So tell the person who posted it.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Pete Becker
Guest
 
Posts: n/a
#21: Jul 22 '05

re: STL std::map erase


Howard wrote:[color=blue]
>
> "Pete Becker" <petebecker@acm.org> wrote in message
> news:40A3D04A.8F9F43A9@acm.org...[color=green]
> > joey tribbiani wrote:[color=darkred]
> > >
> > > Why not the following?
> > >
> > > for (map<...>::iterator i = mymap.begin(); i != mymap.end(); i++) {
> > > if (test(i)) {
> > > i = mymap.erase(i);
> > > }
> > > }[/color]
> >
> > Because map::erase returns void according to the standard. Our
> > implementation returns an iterator, just like vector::erase. The next
> > version of the standard will probably make that change official.
> >[/color]
>
> Even if it *did* return an iterator, the above code would only work if it[/color]

So tell the person who posted it.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jeff Flinn
Guest
 
Posts: n/a
#22: Jul 22 '05

re: STL std::map erase



"Pete Becker" <petebecker@acm.org> wrote in message
news:40A3D78F.E86B2606@acm.org...[color=blue]
> Jeff Flinn wrote:[color=green]
> >
> > "Pete Becker" <petebecker@acm.org> wrote in message
> > news:40A3D04A.8F9F43A9@acm.org...[color=darkred]
> > > joey tribbiani wrote:
> > > >
> > > > Why not the following?
> > > >
> > > > for (map<...>::iterator i = mymap.begin(); i != mymap.end(); i++) {
> > > > if (test(i)) {
> > > > i = mymap.erase(i);
> > > > }
> > > > }
> > >
> > > Because map::erase returns void according to the standard. Our
> > > implementation returns an iterator, just like vector::erase. The next
> > > version of the standard will probably make that change official.[/color]
> >
> > Even with this extension/future std, the above is incorrect. 'i' will be
> > effectively incremented twice for each true 'test(i)'. 'i++' needs to be
> > moved from the for statement to an else clause.
> >[/color]
>
> So tell the person who posted it.[/color]

Assuming this thread is important to the OP, I just did. ;)

I'm also telling someone googling down this thread a few years hence, when
the T::iterator is the standard, that this needs to be corrected.

Jeff F


Pete Becker
Guest
 
Posts: n/a
#23: Jul 22 '05

re: STL std::map erase


Jeff Flinn wrote:[color=blue]
>[color=green]
> > So tell the person who posted it.[/color]
>
> Assuming this thread is important to the OP, I just did. ;)
>[/color]

Sigh. Okay. RESPOND TO THE PERSON WHO ORIGINALLY POSTED THE WORDS THAT
YOU THINK ARE INCORRECT. Is it really that hard to grasp?

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Howard
Guest
 
Posts: n/a
#24: Jul 22 '05

re: STL std::map erase



"Pete Becker" <petebecker@acm.org> wrote in message
news:40A3ED56.1484E024@acm.org...[color=blue]
> Jeff Flinn wrote:[color=green]
> >[color=darkred]
> > > So tell the person who posted it.[/color]
> >
> > Assuming this thread is important to the OP, I just did. ;)
> >[/color]
>
> Sigh. Okay. RESPOND TO THE PERSON WHO ORIGINALLY POSTED THE WORDS THAT
> YOU THINK ARE INCORRECT. Is it really that hard to grasp?
>
> --
>
> Pete Becker
> Dinkumware, Ltd. (http://www.dinkumware.com)[/color]

Why are you so upset??? So our responses fall under yours instead of
directly under joey's. So what? He should be perfectly capable of seeing
the whole conversation, and the context of the responses. (Aren't you?)
It's not like we sent emails to you personally. We posted them to the
newsgroup, as follow-ups to your response. There's no sense in now going
back and posting *again*, directly to joey's post, just so he (and everyone
else) can read the same answer for the third time. Relax a little. We're
not attacking you, just posting follow-up info to the conversation.

-Howard




Pete Becker
Guest
 
Posts: n/a
#25: Jul 22 '05

re: STL std::map erase


Howard wrote:[color=blue]
>
> "Pete Becker" <petebecker@acm.org> wrote in message
> news:40A3ED56.1484E024@acm.org...[color=green]
> > Jeff Flinn wrote:[color=darkred]
> > >
> > > > So tell the person who posted it.
> > >
> > > Assuming this thread is important to the OP, I just did. ;)
> > >[/color]
> >
> > Sigh. Okay. RESPOND TO THE PERSON WHO ORIGINALLY POSTED THE WORDS THAT
> > YOU THINK ARE INCORRECT. Is it really that hard to grasp?
> >[/color]
> Why are you so upset??? So our responses fall under yours instead of
> directly under joey's. So what?[/color]

So you confuse things when you respond to the wrong message. I really
don't see why that's so hard to grasp.
[color=blue]
> He should be perfectly capable of seeing
> the whole conversation, and the context of the responses. (Aren't you?)
> It's not like we sent emails to you personally. We posted them to the
> newsgroup, as follow-ups to your response. There's no sense in now going
> back and posting *again*, directly to joey's post, just so he (and everyone
> else) can read the same answer for the third time.[/color]

Sigh. Nobody suggested posting *again*.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Andrey Tarasevich
Guest
 
Posts: n/a
#26: Jul 22 '05

re: STL std::map erase


Howard wrote:[color=blue][color=green]
>>...
>> Since this function receives its parameter "by value" - yes, it actually
>> receives a copy of the original iterator.
>>[/color]
>
> Ok...but then, what if you were to pass the iterator *by reference* to some
> function instead? What value would the function then get, (considering the
> previously stated rule that the increment side-effect has to be completed
> prior to the calling of the function)? Would a temporary (un-incremented)
> copy be created, passed by reference, and then that copy destroyed after the
> return of the function? (That seems to be the only way to maintain the
> concept of post-increment without violating the side-effect rule.)[/color]

Yes, that's pretty much correct. Note that if you make an attempt to
pass it by non-constant reference, the code simply won't compile,
because post-increment normally returns an rvalue and non-constant
reference cannot be bound to an rvalue. But if the function is declared
with constant reference parameter, then everything will work as you
describe, i.e. the reference will be bound to a temporary object, which
holds the original (un-incremented) value.

--
Best regards,
Andrey Tarasevich

Robbie Hatley
Guest
 
Posts: n/a
#27: Jul 22 '05

re: STL std::map erase



"Pieter Thysebaert" <pieter.thysebaert@toorug.muchac.spambe> wrote in message news:c8010s$a5l$1@gaudi2.UGent.be...[color=blue]
>
>
> Hello,
>
> I've got a question conerning erasing key-value pairs from a std::map while
> iterating over it.
>
> According to the STL docs, erasing an element in a map invalidates all
> iterators pointing to that element
>
> so
>
> for (map<...>::iterator i = mymap.begin(); i != mymap.end(); i++) {
> if (test(i)) {
> mymap.erase(i);
> mymap.insert(newelement);
> }
> }
>
> looks like bad practice, and it does crash when it gets executed, at least
> on one machine i've run such code on.
>
> So my question is, how do I conveniently erase the "current" element in a
> map on the fly while I'm iterating over it? (I admit that this sounds as
> weird in English as it sounds in C++)?
>
> Thanx,
>
> Pieter[/color]

I've run into that situation many times with maps, lists and other containers,
and the easiest solution, I've found, is to get a copy of i called j, decrement i,
then erase (*j). Like so:

map<K, V> mymap; // where K and V are types
map<K, V>::iterator i, j; // get some iterators
for (i = mymap.begin(); i != mymap.end(); i++)
{
if (test(i))
{
j = i; // get temp. copy of i
--i; // gonna kill place where i pointed, so back up!
mymap.erase(j); // erase element where i used to point
mymap.insert(newelement); // automatically sorted; where did it go?
}
}

If i was decremented and (*j) erased, then when execution resumes at the
top of the loop, i will be incremented to the next un-erased item.

Also be aware that there's no guarantee the inserted item went the same
place as the deleted one; map is automatically sorted by key, so the new
element could end up anywhere, depending on sort order.


--
Cheers,
Robbie Hatley
Tustin, CA, USA
email: lonewolfintj at pacbell dot net
web: home dot pacbell dot net slant earnur slant





----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
Closed Thread