|
Evan Balster
|
 |
« on: November 29, 2010, 05:30:12 AM » |
|
for (Entries::iterator i = entries.begin, e = entries.end(); i != e; ++i) { //Stuff } Am I being too anal? Discuss.
|
|
|
|
|
Logged
|
|
|
|
|
BorisTheBrave
|
 |
« Reply #1 on: November 29, 2010, 06:15:01 AM » |
|
I have a co-worker that talked me into doing this, so yes, I do. Not sure whether it really does much, but I did a bit of basic research and most compilers are not capable of optimizing (via loop-invariant hoisting) the more naïve approach into the same code as this. I like to write: typedef Entries::iterator Iterator; for (Iterator i = entries.begin(), e = entries.end(); i != e; ++i) { //Stuff } So that I can pretend I have something like C++0x's auto.
|
|
|
|
|
Logged
|
|
|
|
|
Klaim
|
 |
« Reply #2 on: November 29, 2010, 07:33:25 AM » |
|
Personally I don't pretend :
for( auto it= v.begin(); it != v.end(); ++it ) { doMyThing(*it); }
Or better (but this one I can't with my current compiler):
for( Thin& thing : v ) { doMyThing(thing); }
So until I got this feature in my main compiler, I prefer using lambda :
std::for_each( v.begin(), v.end(), [](Thing& thing) { doMyThing(thing); });
|
|
|
|
|
Logged
|
|
|
|
|
Average Software
|
 |
« Reply #3 on: November 29, 2010, 09:03:19 AM » |
|
for (Entries::iterator i = entries.begin, e = entries.end(); i != e; ++i) { //Stuff } Am I being too anal? Discuss. One thing to note is that your approach might break if you alter this list mid-iteration, as this could invalidate your end iterator.
|
|
|
|
|
Logged
|
|
|
|
|
mcc
|
 |
« Reply #4 on: November 29, 2010, 09:33:26 AM » |
|
for (Entries::iterator i = entries.begin, e = entries.end(); i != e; ++i) { //Stuff } Am I being too anal? Discuss. One thing to note is that your approach might break if you alter this list mid-iteration, as this could invalidate your end iterator. Wouldn't that often invalidate "i" also, though.
|
|
|
|
|
Logged
|
|
|
|
|
Average Software
|
 |
« Reply #5 on: November 29, 2010, 09:36:37 AM » |
|
for (Entries::iterator i = entries.begin, e = entries.end(); i != e; ++i) { //Stuff } Am I being too anal? Discuss. One thing to note is that your approach might break if you alter this list mid-iteration, as this could invalidate your end iterator. Wouldn't that often invalidate "i" also, though. The STL delete functions return the new i.
|
|
|
|
|
Logged
|
|
|
|
|
BorisTheBrave
|
 |
« Reply #6 on: November 29, 2010, 09:38:47 AM » |
|
The STL delete functions return the new i.
They usually return the next i though, meaning that the ++ would be wrong.
|
|
|
|
|
Logged
|
|
|
|
|
Average Software
|
 |
« Reply #7 on: November 29, 2010, 09:41:27 AM » |
|
The STL delete functions return the new i.
They usually return the next i though, meaning that the ++ would be wrong. Which I why I decrement the i after deletion. Should've mentioned that.
|
|
|
|
|
Logged
|
|
|
|
|
Evan Balster
|
 |
« Reply #8 on: November 29, 2010, 10:21:39 AM » |
|
Actually, some of my setup's erase functions don't return the next iterator, which leads to strangeness like this: if (eraseThisEntry) erase(i++); else ++i; I think it's maps or some such. Might be standard. Map iterators don't muck up in that case, at any rate. Also, std::for_each is about as ugly as the nested function hack. C++0x needs to come out soon. struct {int operator()(int v) { return 2 * v; }} doubleIt;
|
|
|
|
|
Logged
|
|
|
|
|
BorisTheBrave
|
 |
« Reply #9 on: November 29, 2010, 10:51:14 AM » |
|
Which I why I decrement the i after deletion. Should've mentioned that.
std::list l{1,2,3}; for(auto i = l.begin(); end = l.end(); i++) { if(*i==1) { i = l.erase(i); i--;// oh bugger } }
|
|
|
|
|
Logged
|
|
|
|
|
Average Software
|
 |
« Reply #10 on: November 29, 2010, 11:03:09 AM » |
|
Which I why I decrement the i after deletion. Should've mentioned that.
std::list l{1,2,3}; for(auto i = l.begin(); end = l.end(); i++) { if(*i==1) { i = l.erase(i); i--;// oh bugger } } I don't believe there's anything wrong with that. It's the same location returned by rend().
|
|
|
|
|
Logged
|
|
|
|
|
BorisTheBrave
|
 |
« Reply #11 on: November 29, 2010, 11:25:49 AM » |
|
That's not how reverse iterators work. Look at this. Reverse iterators work on any bidirectional iterator. They do this by having a screwy dereference operator, but operating on the same range [begin,end], not by having a normal dereference operator, but operating on the range [begin-1, end-1]. This is because it is not legal to get an iterator to begin-1. Even if you don't deference it. | Name | Expression | Precondition | | Predecrement | --i | i is dereferenceable or past-the-end. There exists a dereferenceable iterator j such that i == ++j |
That said, it seems very unlikely an implementation depends on it.
|
|
|
|
|
Logged
|
|
|
|
|
Average Software
|
 |
« Reply #12 on: November 29, 2010, 11:32:14 AM » |
|
That's not how reverse iterators work. Look at this. Reverse iterators work on any bidirectional iterator. They do this by having a screwy dereference operator, but operating on the same range [begin,end], not by having a normal dereference operator, but operating on the range [begin-1, end-1]. This is because it is not legal to get an iterator to begin-1. Even if you don't deference it. | Name | Expression | Precondition | | Predecrement | --i | i is dereferenceable or past-the-end. There exists a dereferenceable iterator j such that i == ++j |
That said, it seems very unlikely an implementation depends on it. Interesting. It should be noted though that a lot of that SGI documentation is pre-standard and may be out of date. I'll see if I can find a concrete reference to this in the standards document, and if this is in fact wrong, I'll stop doing it right away.
|
|
|
|
|
Logged
|
|
|
|
|
Average Software
|
 |
« Reply #13 on: November 29, 2010, 11:38:51 AM » |
|
That's not how reverse iterators work. Look at this. Reverse iterators work on any bidirectional iterator. They do this by having a screwy dereference operator, but operating on the same range [begin,end], not by having a normal dereference operator, but operating on the range [begin-1, end-1]. This is because it is not legal to get an iterator to begin-1. Even if you don't deference it. | Name | Expression | Precondition | | Predecrement | --i | i is dereferenceable or past-the-end. There exists a dereferenceable iterator j such that i == ++j |
That said, it seems very unlikely an implementation depends on it. Interesting. It should be noted though that a lot of that SGI documentation is pre-standard and may be out of date. I'll see if I can find a concrete reference to this in the standards document, and if this is in fact wrong, I'll stop doing it right away. Addendum: The last draft of the C++0x standard that I downloaded confirms this. I assume it's true for C++98 as well. In either case, I'll certainly stop doing it, in preparation for the new standard if nothing else.
|
|
|
|
|
Logged
|
|
|
|
|
LemonScented
|
 |
« Reply #14 on: November 29, 2010, 04:09:51 PM » |
|
for(int i = 0; i < numberOfThings; ++i) { // Stuff } To hell with your new-fangled iterators and STL garbage! REAL men do it with good old fashioned arrays, indexed with good old fashioned ints (signed ints, mind). Get off my lawn!
|
|
|
|
|
Logged
|
|
|
|
|