3

Here is a simple question I have been wondering about for a long time : When I do a loop such as this one :

for (int i = 0; i < myVector.size() ; ++i) {
    // my loop
}

As the condition i < myVector.size() is checked each time, should I store the size of the array inside a variable before the loop to prevent the call to size() each iteration ? Or is the compiler smart enough to do it itself ?

mySize = myVector.size();   
for (int i = 0; i < mySize ; ++i) {
    // my loop
}

And I would extend the question with a more complex condition such as i < myVector.front()/myVector.size()

Edit : I don't use myVector inside the loop, it is juste here to give the ending condition. And what about the more complex condition ?

3
  • 1
    possible duplicate of Can compiler optimization elminate a function repeatedly called in a for-loop's conditional? Commented May 12, 2015 at 9:19
  • Thanks all for your answers ! But no one did answer about the more complex condition.. Is the compiler smart enough to see that the result of the division will not change as I don't modify the vector inside the loop ? Commented May 12, 2015 at 9:35
  • 1
    I have no idea if (or: which) compilers are smart enough to notice that myVector.front()/myVector.size() is a constant expression (provided you do not modify the vector inside the loop). Ayway that's a matter of optimization, and results may differ between compiler versions and optimization modes. So I won't tell you whether you should calculate the terminating value before the loop or not; just compile your code to assembler source and see if the compiler produces the full calculations on each iteration. If so, then optimizing by yourself may make sense. Commented May 12, 2015 at 12:27

5 Answers 5

2

The answer depends mainly on the contents of your loop–it may modify the vector during processing, thus modifying its size.

However if the vector is just scanned you can safely store its size in advance:

for (int i = 0, mySize = myVector.size(); i < mySize ; ++i) {
    // my loop
}

although in most classes the functions like 'get current size' are just inline getters:

class XXX
{
public:
    int size() const { return mSize; }
    ....
private:
    int mSize;
    ....
};

so the compiler can easily reduce the call to just reading the int variable, consequently prefetching the length gives no gain.

Sign up to request clarification or add additional context in comments.

Comments

1

If you are not changing anything in vector (adding/removing) during for-loop (which is normal case) I would use foreach loop

for (auto object : myVector)
{
  //here some code
}

or if you cannot use c++11 I would use iterators

for (auto it = myVector.begin(); it != myVector.end(); ++it)
{
  //here some code
}

1 Comment

but why to use iteration over foreach or iterator? author didn't mention that he cannot use foreach for example
1

I'd say that

for (int i = 0; i < myVector.size() ; ++i) {
    // my loop
}

is a bit safer than

mySize = myVector.size();   
for (int i = 0; i < mySize ; ++i) {
    // my loop
}

because the value of myVector.size() may change (as result of , e.g. push_back(value) inside the loop) thus you might miss some of the elements.
If you are 100% sure that the value of myVector.size() is not going to change, then both are the same thing.
Yet, the first one is a bit more flexible than the second (other developer may be unaware that the loop iterates over fixed size and he might change the array size). Don't worry about the compiler, he's smarter than both of us combined.

5 Comments

or even better readability would be achieved with const mySize = myVector.size(); - you can clearly see mySize is constant and not about to change in loop.
it just make mySize not to change, the array can still change in size.
Though I'd say that modifying a vector within a loop is anyway a bad idea, at least unless you do absolutely understand what are you doing. For example, if you insert an element into vector's middle, you still might lose some of the elements. What's worse it that in a different style of the same loop, like with iterator and begin()/end() modifying a vector might lead to a bigger problems.
yes but it is explicitly saying that the iteration count is fixed at the beginning and should not be changed, if someone will try to change it it will be const modification violation, in some algorithms you are pushing the vector end and don't want to iterate through the new elements... it really depends on use case.
it is a common practice to iterate over an array and delete an element if it does not satisfy a condition. bad or good practice, it is pretty common..
0

The overhead is very small. vector.size() does not recalculate anything, but simply returns the value of the private size variable..

it is safer than pre-buffering the value, as the vectors internal size variable is changed when an element is popped or pushed to/from the vector..

compilers can be written to optimize this out, if and only if, it can predict that the vector is not changed by ANYTHING while the for loop runs. That is difficult to do if there are threads in there.

but if there isn't any threading going on, it's very easy to optimize it.

Comments

0

Any smart compiler will probably optimize this out. However just to be sure I usually lay out my for loops like this:

for (int i = myvector.size() -1; i >= 0; --i)
{

}

A couple of things are different:

  • The iteration is done the other way around. Although this shouldn't be a problem in most cases. If it is I prefer David Haim's method.

  • The --i is used rather than a i--. In theory the --i is faster, although on most compilers it won't make a difference.

If you don't care about the index this:

for (int i = myvector.size(); i > 0; --i)
{

}

Would also be an option. Altough in general I don't use it because it is a bit more confusing than the first. And will not gain you any performance.

For a type like a std::vector or std::list an iterator is the preffered method:

for (std::vector</*vectortype here*/>::iterator i = myVector.begin(); i != myVector.end(); ++i)
{

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.