 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Kelly Mandrake Guest
|
Posted: Mon Feb 28, 2005 3:54 am Post subject: std::map iterator and clearing |
|
|
I have been learning about STL's map class. I see that I can clear a
hashmap by useing the method clear, however I decided to try to clear
the hash with a for loop. Since erase can take an iterator as a
position I thought I could do something like this:
hashTable::iterator i;
for (i = phoneBook.begin(); i != phoneBook.end(); i++)
{
cout << i->first << endl;
phoneBook.erase(i);
}
I get an access violation, I think the reason is that the condition is
never false , and thus the loop continues to now access memory beyond
phoneBook. But I cannot see why. If i comment out the erase line I am
ok, but what I am trying to do is to clear the phoneBook. Without
useing clear method.
Could somebody give me a hint, is it true the condition is never false?
What could possibly be causeing that.
|
|
| Back to top |
|
 |
red floyd Guest
|
Posted: Mon Feb 28, 2005 6:45 am Post subject: Re: std::map iterator and clearing |
|
|
Kelly Mandrake wrote:
| Quote: | I have been learning about STL's map class. I see that I can clear a
hashmap by useing the method clear, however I decided to try to clear
|
hashmap is not a standard class.
| Quote: | the hash with a for loop. Since erase can take an iterator as a
position I thought I could do something like this:
hashTable::iterator i;
for (i = phoneBook.begin(); i != phoneBook.end(); i++)
{
cout << i->first << endl;
phoneBook.erase(i);
|
At this point, i is an invalid iterator. I suspect the correct code
should be:
for (i = phoneBook.begin(); i != phoneBook.end() ; )
{
cout << i->first.endl;
i = phoneBook.erase(i); // guess, don't know what
// hashmap::erase returns
}
| Quote: | }
I get an access violation, I think the reason is that the condition is
never false , and thus the loop continues to now access memory beyond
phoneBook. But I cannot see why. If i comment out the erase line I am
ok, but what I am trying to do is to clear the phoneBook. Without
useing clear method.
Could somebody give me a hint, is it true the condition is never false?
What could possibly be causeing that.
|
|
|
| Back to top |
|
 |
red floyd Guest
|
Posted: Mon Feb 28, 2005 6:46 am Post subject: Re: std::map iterator and clearing |
|
|
red floyd wrote:
| Quote: | Kelly Mandrake wrote:
I have been learning about STL's map class. I see that I can clear a
hashmap by useing the method clear, however I decided to try to clear
hashmap is not a standard class.
the hash with a for loop. Since erase can take an iterator as a
position I thought I could do something like this:
hashTable::iterator i;
for (i = phoneBook.begin(); i != phoneBook.end(); i++)
{
cout << i->first << endl;
phoneBook.erase(i);
At this point, i is an invalid iterator. I suspect the correct code
|
Sorry, meant to say, i is invalid, so i++ has no meaning.
| Quote: | should be:
for (i = phoneBook.begin(); i != phoneBook.end() ; )
{
cout << i->first.endl;
i = phoneBook.erase(i); // guess, don't know what
// hashmap::erase returns
}
}
I get an access violation, I think the reason is that the condition is
never false , and thus the loop continues to now access memory beyond
phoneBook. But I cannot see why. If i comment out the erase line I am
ok, but what I am trying to do is to clear the phoneBook. Without
useing clear method.
Could somebody give me a hint, is it true the condition is never false?
What could possibly be causeing that.
|
|
|
| Back to top |
|
 |
Kelly Mandrake Guest
|
Posted: Mon Feb 28, 2005 6:18 pm Post subject: Re: std::map iterator and clearing |
|
|
sorry, i forgot to say i typedefed hashmap like so
typedef map<string, string> hashTable;
unfortunately also when I try i = phoneBook.erase(i) I get no match for
'operator=' in 'i = (&phoneBook)->......
I think the reason is my implementation of STL returns void from erase,
this is my guess after reading an article about the difernt
implementations of STL. Actualy this code I wrote was a test because
im trying to port code writen for msvc.
is the reason i is invalid because i didnt mention my typedef? Because
it will compile if i comment out the line phoneBook.erase(i); it will
work fine I think i++ is ok in my case, but what exactly hapens when
erase is called? The documentation i found on microsft does not seem
to explain this.
|
|
| Back to top |
|
 |
red floyd Guest
|
Posted: Mon Feb 28, 2005 7:13 pm Post subject: Re: std::map iterator and clearing |
|
|
Kelly Mandrake wrote:
| Quote: | sorry, i forgot to say i typedefed hashmap like so
typedef map<string, string> hashTable;
unfortunately also when I try i = phoneBook.erase(i) I get no match for
'operator=' in 'i = (&phoneBook)->......
I think the reason is my implementation of STL returns void from erase,
this is my guess after reading an article about the difernt
implementations of STL. Actualy this code I wrote was a test because
im trying to port code writen for msvc.
is the reason i is invalid because i didnt mention my typedef? Because
it will compile if i comment out the line phoneBook.erase(i); it will
work fine I think i++ is ok in my case, but what exactly hapens when
erase is called? The documentation i found on microsft does not seem
to explain this.
|
You're right. std::map::erase doesn't return anything, probably because
the tree gets re-sorted/rebalanced after deleting, and iterator ordering
may no longer make sense.
If you're just ripping through in order, you might want to try:
while (!phoneBook.empty())
{
i = phoneBook.begin();
// do stuff with i
phoneBook.erase(i);
}
Or, alternatively
std::for_each(phoneBook.begin(),
phoneBook.end(),
DoSomethingWithPhoneBookFunctor());
phoneBook.clear();
|
|
| Back to top |
|
 |
Kelly Mandrake Guest
|
Posted: Mon Feb 28, 2005 7:38 pm Post subject: Re: std::map iterator and clearing |
|
|
Well that worked, and It never ocured to me to test for empty. So
every time i call erase the tree is resorted, very interesting. Still
trying to figure out things I looked up the documentation for end and i
was suprized, one reference mentioned that if the map is empty then
end() is the same as begin(), but when I tested for begin I got same
results. But it makes sence now you mention the tree gets resorted, so
end gets confused.
Both your examples worked thank you for these. I decided to try one on
my own after reviewing yours and came up with
for (hashTable::iterator i = phoneBook.begin(); !phoneBook.empty();
i++)
{
cout << i->first << endl;
phoneBook.erase(i);
}
|
|
| Back to top |
|
 |
red floyd Guest
|
Posted: Tue Mar 01, 2005 3:43 am Post subject: Re: std::map iterator and clearing |
|
|
Kelly Mandrake wrote:
| Quote: | Well that worked, and It never ocured to me to test for empty. So
every time i call erase the tree is resorted, very interesting. Still
trying to figure out things I looked up the documentation for end and i
was suprized, one reference mentioned that if the map is empty then
end() is the same as begin(), but when I tested for begin I got same
results. But it makes sence now you mention the tree gets resorted, so
end gets confused.
Both your examples worked thank you for these. I decided to try one on
my own after reviewing yours and came up with
for (hashTable::iterator i = phoneBook.begin(); !phoneBook.empty();
i++)
{
cout << i->first << endl;
phoneBook.erase(i);
}
|
Still not good. After the phoneBook.erase(i) statement, i is not longer
a valid iterator, and the i++ in the loop is UB.
Also, when dealing with iterators, it's generally considered better form
to use the preincrement (++i) form unless there's a really good reason
for postincrement.
|
|
| Back to top |
|
 |
Kelly Mandrake Guest
|
Posted: Tue Mar 01, 2005 5:27 pm Post subject: Re: std::map iterator and clearing |
|
|
It did compile and execute ok for me though, all three seem to work.
May I ask which STL you are useing, I am useing g++ 3.4 with stl that
came with it. I will remember to use the preincrement from now on,
thanks for this.
|
|
| Back to top |
|
 |
msalters Guest
|
Posted: Wed Mar 02, 2005 4:28 pm Post subject: Re: std::map iterator and clearing |
|
|
red floyd wrote:
| Quote: | Kelly Mandrake wrote:
I thought I could do something like this:
hashTable::iterator i;
for (i = phoneBook.begin(); i != phoneBook.end(); i++)
{
cout << i->first << endl;
phoneBook.erase(i);
At this point, i is an invalid iterator. I suspect the correct code
should be:
for (i = phoneBook.begin(); i != phoneBook.end() ; )
{
cout << i->first.endl;
i = phoneBook.erase(i); // guess, don't know what
// hashmap::erase returns
}
|
Basic idea is OK, but this depends on the return type of erase.
This is one of the few cases where post-increment
is useful (++i is at least as efficient and often more)
for (i = phoneBook.begin(); i != phoneBook.end() ; )
{
cout << i->first.endl;
phoneBook.erase(i++);
}
the point is that i++ returns the old value as a temporary. Usually
that's totally redundant, but in this case it's very useful. Once
erased, the temporary iterator is destroyed.
This will also work if empty, because an empty container has
begin==end (another reason why STL uses half-open ranges).
(Note: hashmap is not a std:: class yet, so what you've got may
in fact invalidate all iterators on an erase. So, RTFM )
HTH,
Michiel Salters
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|