hamster on wheels
hamster on wheels

Reputation: 2893

Would Iterator loop call end() for many times?

#include <vector>
#include <iostream>

class Range {
    typedef typename std::vector<int> Vec;
    typedef typename Vec::iterator Iterator;
public:
    Range(Vec& vec, const int start_id, const int size)
            : vec_{vec},
              it_begin_{vec_.begin() + start_id},
              it_end_  {vec_.begin() + start_id + size}
    {}
    Iterator& begin() {return it_begin_;}
    Iterator& end()   {return it_end_;}
private:
    Vec& vec_;
    Iterator it_begin_;
    Iterator it_end_;
};

int main()
{
    std::vector<int> a;
    a.resize(100);
    Range range(a,0,10);
    for (auto it = range.begin(); it != range.end(); ++it) { // Line A
        std::cout << it - range.begin() << "\n"; // Line B
    }
}

Assembly here

Suppose I use optimization (like g++ -Ofast).

In Line A, would the program call range.end() for many times, instead of saving the value of range.end() and compare that value with it in every iteration of the loop?

In Line B, would the program call range.begin() for many times, instead of saving the value of range.begin() for the whole loop and then subtract that value from it in every iteration of the loop?

Upvotes: 4

Views: 493

Answers (3)

SergeyA
SergeyA

Reputation: 62583

It is hard to predict what optimizer would and would not do on a given optimization level. While this particular transformation is trivial, and usually done whenever inlining is allowed, it is not guaranteed.

When in doubt, I'd follow the old Russian saying, loosely translated as 'Have faith in the optimizer, but do not be a dummy yourself!'. So I would use a const variable to store the result of the call. It will first and foremost make the code more readable, and as a nice side effect it might help some paradoxical optimizers. And a good optimizer will eliminate the variable anyways.

Upvotes: 4

NiVeR
NiVeR

Reputation: 9786

The access of .end() member has a constant complexity, it is read once and it is used as the limit in the loop. You can check this example for map container, but it applies for others as well.

Upvotes: 1

Toby Speight
Toby Speight

Reputation: 30831

In your code, the optimizer can see the implementations of begin() and end(). It can inline them, and hoist invariants out of the loop.

The answer would likely be different if begin() and end() were in a different translation unit than the main(), as link-time is usually too late for such optimizations.

Upvotes: 4

Related Questions