Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to "verify" your details, making threats, or asking for money, are
spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the
password reset link.
Entire forum
➜ Programming
➜ STL
➜ list for loops
It is now over 60 days since the last post. This thread is closed.
Refresh page
Pages: 1
2
Posted by
| David Haley
USA (3,881 posts) Bio
|
Date
| Reply #15 on Sat 19 Feb 2005 02:03 AM (UTC) |
Message
| Ah yes, it's remove, not erase. Erase is for erasing given iterator(s) and remove is for values. |
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | Top |
|
Posted by
| Samson
USA (683 posts) Bio
|
Date
| Reply #16 on Sat 19 Feb 2005 03:32 PM (UTC) |
Message
|
for( ich = ch->in_room->people.begin(); ich != ch->in_room->people.end(); )
{
rch = (*ich);
ich++;
I've been noticing a pattern in crashes I'm weeding out when using std::list and figured I'd share what I've found so far.
It seems that iterating over a list like this is fine - so long as there's soemthing in it. Seems that every one of my crashes relating to lists dies in the for loop statement for them. So my guess is that while the list still has a valid iterator, the contents of the member are not. I'm not sure how else to go about making sure this doesn't happen since I was under the impression that if you did list.remove( member ) it took the member out of the list.
All of the ones I've found so far could potentially be empty lists, so I suppose I need to know: Do you have to verify the list is not empty before walking it ( with a list.empty() check ) ? | Top |
|
Posted by
| David Haley
USA (3,881 posts) Bio
|
Date
| Reply #17 on Sat 19 Feb 2005 04:05 PM (UTC) |
Message
| No, when the list is empty, list.begin() == list.end() so the loop should not get past the condition part of the for(;;) statement.
Where are you calling remove? |
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | Top |
|
Posted by
| Samson
USA (683 posts) Bio
|
Date
| Reply #18 on Sat 19 Feb 2005 04:20 PM (UTC) |
Message
| In this particular case, it would be when the target dies in combat. Although they aren't technically removed until clean_char_queue takes them out. And I moved clean_char_queue down past all of the update handlers in update.c, so if checking the list to be sure it's empty first isn't going to be helpful, I've got a much nastier problem lurking. :( | Top |
|
Posted by
| Nick Gammon
Australia (23,046 posts) Bio
Forum Administrator |
Date
| Reply #19 on Sun 20 Feb 2005 12:23 AM (UTC) |
Message
| You can certainly iterate over empty lists, the design specifically allows for that, which is why begin () points to the the start of a list, and end () points to one past the end of a list, so that the condition begin () == end () is true for empty lists (or maps or anything else).
However you need to be cautious about removing things from a list you are iterating through. The safe way is to increment the iterator before doing the remove. There is an example in the forum here, here it is again:
for (people_map::iterator j = people.begin (); j != people.end (); )
{
if (j->second.GetAge () == 100)
people.erase (j++); // iterator is advanced before the erase occurs
else
++j; // advance the iterator
} // end of erase loop
Notice that the way it is written, things will work correctly here. :) |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Samson
USA (683 posts) Bio
|
Date
| Reply #20 on Sun 20 Feb 2005 01:13 AM (UTC) |
Message
| So what are the consequences of doing something like so then:
for( ich = ch->in_room->people.begin(); ich != ch->in_room->people.end(); )
{
rch = (*ich);
ich++;
ch->in_room->people.remove( rch );
...rest of function...
It appears to me that as long as the iterator is advanced to a valid location before calling for removal that it should work. What's the advantage of using erase() ? And suppose when the erase() call is needed you don't know what the current position of the iterator is in the list? | Top |
|
Posted by
| Greven
Canada (835 posts) Bio
|
Date
| Reply #21 on Sun 20 Feb 2005 01:45 AM (UTC) |
Message
| If you don't know the iterator for the list, you can use find to retreive it, so that no iteration is required at all. |
Nobody ever expects the spanish inquisition!
darkwarriors.net:4848
http://darkwarriors.net | Top |
|
Posted by
| Raz
(32 posts) Bio
|
Date
| Reply #22 on Sun 20 Feb 2005 04:17 AM (UTC) |
Message
|
Quote: Most likely, yes, because VARIABLE is what he's using as the value of the iterator. So it makes sense to assign the value of the iterator to VARIABLE at every pass.
I said that because such tricks are usually error prone to the hidden logic of C++. It really doesn't make sense to assign it in the conditional, but I would guess that he would have no other way to assign the variable and get the form he wants. (I don't know if that made complete sense.)
Quote: Using for_each is major a pain in the behind because every time you use it, you need to create an external function - and if you want to use local variables, you have to make a functor, and pass it all kinds of variables in the constructor - basically, you have an awful lot of overhead.
You're assuming inlining a function guarantees better performance, which is not true. It is better to leave it up to the compiler via a function object than it is to write code in explicitly by hand. The compiler is almost always a much better chooser of how to optimize the code than the programmer.
Quote: IMHO for_each is not a good solution for specific applications; it's a very good solution if you want to provide a generic way of mapping over the elements of a container.
If you want a specific solution, a different std:: algorithm would be better than std::for_each, of course. std::for_each is just the most general way when there isn't a more specific solution available. |
-Raz
C++ Wiki: http://danday.homelinux.org/dan/cppwiki/index.php | Top |
|
Posted by
| Raz
(32 posts) Bio
|
Date
| Reply #23 on Sun 20 Feb 2005 04:32 AM (UTC) |
Message
|
Quote: It appears to me that as long as the iterator is advanced to a valid location before calling for removal that it should work.
As long as the iterator is not referencing that element you should be ok. It is probably best to use erase() when you are using iterators and remove() when you are dealing just with values.
Quote: What's the advantage of using erase() ?
erase() is probably a constant-time operation (I'm 99% sure, but I don't have my standard with me). remove(), OTOH, is linear and erases all the elements that compare equal to the value passed.
Quote: And suppose when the erase() call is needed you don't know what the current position of the iterator is in the list?
Right. |
-Raz
C++ Wiki: http://danday.homelinux.org/dan/cppwiki/index.php | Top |
|
Posted by
| David Haley
USA (3,881 posts) Bio
|
Date
| Reply #24 on Sun 20 Feb 2005 05:48 AM (UTC) |
Message
|
Quote: You're assuming inlining a function guarantees better performance, which is not true. It is better to leave it up to the compiler via a function object than it is to write code in explicitly by hand. The compiler is almost always a much better chooser of how to optimize the code than the programmer. You didn't understand my point. I'm not talking about optimization, I'm talking about a pain for the programmer to have to leave little functors lying around every time s/he wants to iterate over a list.
Quote: It really doesn't make sense to assign it in the conditional, but I would guess that he would have no other way to assign the variable and get the form he wants. I guess that it doesn't make sense if you think about the conditional as a test for continuing, but it certainly works. I wouldn't do it that way, but as far as I can tell it's the only way for him to use the macro the way he wants to.
Quote: If you don't know the iterator for the list, you can use find to retreive it, so that no iteration is required at all. Except for the iteration to find it. :P |
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | Top |
|
Posted by
| Greven
Canada (835 posts) Bio
|
Date
| Reply #25 on Sun 20 Feb 2005 06:06 AM (UTC) Amended on Sun 20 Feb 2005 06:07 AM (UTC) by Greven
|
Message
| Heh, the macro isn't exactly important, just handy for our purposes, as it does its job in fairly clean code. As for my use of iteration, I meant it as the verb, not the noun :) |
Nobody ever expects the spanish inquisition!
darkwarriors.net:4848
http://darkwarriors.net | Top |
|
The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).
To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.
79,735 views.
This is page 2, subject is 2 pages long:
1
2
It is now over 60 days since the last post. This thread is closed.
Refresh page
top