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

Discussion in 'C++' started by Steven T. Hatton, Aug 16, 2004.

  1. 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
    Steven T. Hatton, Aug 16, 2004
    #1
    1. Advertising

  2. Steven T. Hatton

    Ian Guest

    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
    Ian, Aug 16, 2004
    #2
    1. Advertising

  3. In message <>, Steven T. Hatton
    <> 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
    Richard Herring, Aug 16, 2004
    #3
  4. 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
    Steven T. Hatton, Aug 16, 2004
    #4
  5. Steven T. Hatton

    tom_usenet Guest

    On Mon, 16 Aug 2004 02:48:16 -0400, "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.


    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
    tom_usenet, Aug 16, 2004
    #5
  6. Steven T. Hatton

    Greg Schmidt Guest

    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
    Trawna Publications http://www.trawna.com/
    Greg Schmidt, Aug 16, 2004
    #6
  7. 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
    Steven T. Hatton, Aug 22, 2004
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Lucas Tam
    Replies:
    0
    Views:
    735
    Lucas Tam
    Apr 13, 2005
  2. Chris \( Val \)

    Re: for(size_t a=begin();a!=end();++a){}

    Chris \( Val \), Jul 13, 2003, in forum: C++
    Replies:
    2
    Views:
    351
    John Harrison
    Jul 14, 2003
  3. yezi

    Why different from expectation

    yezi, Nov 28, 2005, in forum: C Programming
    Replies:
    10
    Views:
    504
    Keith Thompson
    Nov 30, 2005
  4. debolina
    Replies:
    0
    Views:
    809
    debolina
    Jun 16, 2011
  5. Kurt M. Dresner

    do...end vs. begin..end

    Kurt M. Dresner, Jul 11, 2003, in forum: Ruby
    Replies:
    3
    Views:
    112
Loading...

Share This Page