By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,804 Members | 1,666 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,804 IT Pros & Developers. It's quick & easy.

Reasonable expectation: for(it = v.begin(); it != v.end(); it++)

P: n/a
Suppose I have the following:
vector<T> v(20);
for(vector<T>::it = v.begin(); it != v.end(); ++it){/*do something*/}

What can I reasonably expect of a compiler regarding the call to v.end()?
IOW, does it cost more to evaluate v.end() for each iteration than it does
to use

size_t sz = v.size();
for(size_t i = 0; i < sz; i++){/*do something*/}
?

I'm talking about reasonable expectations not what a specific compiler does.

I have to wonder what the advantage of the first form above is over the
second. I know there are functions in <algorithm> which require iterators,
but for purposes of traversing a sequence in a for() loop, it seems
generally more convenient to use the 'traditional' array-style with []
subscripting. That, however, is not what I see in a lot of C++ literature.
--
STH
Hatton's Law: "There is only One inviolable Law"
KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
Mozilla: http://www.mozilla.org
Jul 22 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
Ian
Steven T. Hatton wrote:
Suppose I have the following:
vector<T> v(20);
for(vector<T>::it = v.begin(); it != v.end(); ++it){/*do something*/}

What can I reasonably expect of a compiler regarding the call to v.end()?
IOW, does it cost more to evaluate v.end() for each iteration than it does
to use

size_t sz = v.size();
for(size_t i = 0; i < sz; i++){/*do something*/}
?

I'm talking about reasonable expectations not what a specific compiler does.

I have to wonder what the advantage of the first form above is over the
second. I know there are functions in <algorithm> which require iterators,
but for purposes of traversing a sequence in a for() loop, it seems
generally more convenient to use the 'traditional' array-style with []
subscripting. That, however, is not what I see in a lot of C++ literature.


For vector, it's six of one and half a dozen of the other. end() may
just be an inline method and an iterator may just be a pointer. Don't
forget [] will also be a member call.

Another reason for using iterators is you may end up changing container
type as your design evolves. [] is far from trivial on a map. So the
iterator form makes your code more general.

Ian
Jul 22 '05 #2

P: n/a
In message <6N********************@speakeasy.net>, Steven T. Hatton
<su******@setidava.kushan.aa> writes
Suppose I have the following:
vector<T> v(20);
for(vector<T>::it = v.begin(); it != v.end(); ++it){/*do something*/}

What can I reasonably expect of a compiler regarding the call to v.end()?
IOW, does it cost more to evaluate v.end() for each iteration than it does
to use

size_t sz = v.size();
for(size_t i = 0; i < sz; i++){/*do something*/}
?

I'm talking about reasonable expectations not what a specific compiler does.
If you're really, justifiably (i.e. a profiler told you so!) worried
about the cost of repeatedly calling v.end(), why not just do this:

for (whatever::iterator it=v.begin(), e=e.end(); it!=e; ++it) {...}

?
I have to wonder what the advantage of the first form above is over the
second. I know there are functions in <algorithm> which require iterators,
but for purposes of traversing a sequence in a for() loop, it seems
generally more convenient to use the 'traditional' array-style with []
subscripting.
Until someone decides to substitute a list for the vector.
That, however, is not what I see in a lot of C++ literature.


--
Richard Herring
Jul 22 '05 #3

P: n/a
Richard Herring wrote:

If you're really, justifiably (i.e. a profiler told you so!) worried
about the cost of repeatedly calling v.end(), why not just do this:

for (whatever::iterator it=v.begin(), e=e.end(); it!=e; ++it) {...}

?


I haven't started messing with a profiler yet - it's not a bad suggestion -,
but in some of the things I do, number crunching is an issue.

Yes, that is an option. For the sake of readability, I would prefer:

whatever::iterator e=v.end();
for (whatever::iterator it=v.begin(); it!=e; ++it) {...}

That will work 99.9% of the time. I am very unlikely to try to grow the
vector in the for() loop, however...

--
STH
Hatton's Law: "There is only One inviolable Law"
KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
Mozilla: http://www.mozilla.org
Jul 22 '05 #4

P: n/a
On Mon, 16 Aug 2004 02:48:16 -0400, "Steven T. Hatton"
<su******@setidava.kushan.aa> wrote:
Suppose I have the following:
vector<T> v(20);
for(vector<T>::it = v.begin(); it != v.end(); ++it){/*do something*/}

What can I reasonably expect of a compiler regarding the call to v.end()?
IOW, does it cost more to evaluate v.end() for each iteration than it does
to use

size_t sz = v.size();
for(size_t i = 0; i < sz; i++){/*do something*/}
?

I'm talking about reasonable expectations not what a specific compiler does.
It certainly makes the job of the compiler. If your "do something" is
sufficiently complex, the call can't be optimized away (although it
will almost certainly be inlined). A common technique is to do:

for(vector<T>::it = v.begin(), end = v.end();
it != end;
++it){
/*do something*/
}
I have to wonder what the advantage of the first form above is over the
second. I know there are functions in <algorithm> which require iterators,
but for purposes of traversing a sequence in a for() loop, it seems
generally more convenient to use the 'traditional' array-style with []
subscripting. That, however, is not what I see in a lot of C++ literature.


The subscripting is only efficient for std::vector; in that specific
case, using subscripting is fine. For other containers you have to use
iterators (and for std::deque it may be more efficient).

Tom
Jul 22 '05 #5

P: n/a
On Mon, 16 Aug 2004 07:26:13 -0400, Steven T. Hatton wrote:
Richard Herring wrote:

If you're really, justifiably (i.e. a profiler told you so!) worried
about the cost of repeatedly calling v.end(), why not just do this:

for (whatever::iterator it=v.begin(), e=e.end(); it!=e; ++it) {...}

?
I haven't started messing with a profiler yet - it's not a bad suggestion -,
but in some of the things I do, number crunching is an issue.


In 11 years in the industry, I've only ever once needed to get into
profiling. Then again, I may be the exception to the rule, most of what I
write spends its time waiting for user input, and whether it takes 0.1 or
0.3 seconds to respond is largely irrelevant.
Yes, that is an option. For the sake of readability, I would prefer:

whatever::iterator e=v.end();
for (whatever::iterator it=v.begin(); it!=e; ++it) {...}
The drawback of this is that the scope of e is now much larger than if it
were declared in the for statement.
That will work 99.9% of the time. I am very unlikely to try to grow the
vector in the for() loop, however...


If you grow the vector inside the for loop, then you're asking for all
kinds of trouble. Not only will end() change, but your "it" iterator may
be invalidated by a reallocation. (Of course, you might be able to ensure
that enough space is reserved before entering the for loop.)

--
Greg Schmidt gr***@trawna.com
Trawna Publications http://www.trawna.com/
Jul 22 '05 #6

P: n/a
Greg Schmidt wrote:
On Mon, 16 Aug 2004 07:26:13 -0400, Steven T. Hatton wrote:

I haven't started messing with a profiler yet - it's not a bad suggestion
-, but in some of the things I do, number crunching is an issue.


In 11 years in the industry, I've only ever once needed to get into
profiling. Then again, I may be the exception to the rule, most of what I
write spends its time waiting for user input, and whether it takes 0.1 or
0.3 seconds to respond is largely irrelevant.


Certainly most of what I am likely to write falls into that category as
well. It may be worth considering how much you are asking the processor to
do even if your own response time isn't an issue. In most cases it is more
reasonable to focus on writing understandable code than on writing highly
optimize code.
Yes, that is an option. For the sake of readability, I would prefer:

whatever::iterator e=v.end();
for (whatever::iterator it=v.begin(); it!=e; ++it) {...}


The drawback of this is that the scope of e is now much larger than if it
were declared in the for statement.


Agreed. I will say that I tend to keep the size of any given function fairly
small, so scope does not become a major issue. In the above case, I would
probably prefer to mess up the containing scope a bit, rather than write
hard to read code.

But all of this seems moot now that I have given it further thought.
v.end() is most likely going to be represented as a pointer with a fixed
memory location containing the value of the address immediately following
the last element of the vector's physical representation. The 'management'
members of the vector are unlikely to be relocated if the vector is
resized. That means v.end() will have a fixed address throughout its
lifetime. The value stored at that address will be changed if the vector
is resized. The comparison `it != v.end()' is between pointer values, so
using e=v.end() buys you nothing. `whatever::iterator e' is as indirect as
v.end().

--
STH
Hatton's Law: "There is only One inviolable Law"
KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
Mozilla: http://www.mozilla.org
Jul 22 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.