Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: Is arr.size() a good condition for a loop?

If there is a vector called arr which contains a huge number of data, and I am to print all the values in that vector. I would either use:

int arr_size = arr.size();
for(int i=0; i<arr_size; ++i) {//print the values}

or implement it this way:

for(int i=0; i<arr.size(); ++i) {//print the values}

In my opinion, the first way of implementation will fetch the size of the vector into the cache and hence make the condition faster after the first miss. What about the second implementation? Is it slower? Will the system call the size() method every time when it meet the condition?

Edit: Let's say it is using C++.

like image 825
xiaoyao Avatar asked Apr 30 '12 10:04

xiaoyao


3 Answers

Generalising for a loop with arbirary body, there is one critical difference between the two variants you have given: what if the size of arr changes during the loop?

For the second case, if the compiler can assume that it doesn't change then it can optimize the loop so arr.size() is only called once, and the generated code becomes about the same as for the first case.

But if the loop body so much as calls an external function (highly likely) then it can't make this assumption anymore and must check arr.size() every loop iteration.

Having said that arr.size() will probably work out to a simple structure member access which would be no slower than storing the value in a local variable, so there isn't much to be gained out of using the first variant anyway. Unless arr is a pointer or reference in which case it's an indirect and then an access, so the first version would be a litte faster.

If it's a particularly commonly run loop and you have to compile without optimisation for some reason, you might want to go with the first case to speed it up.

But then, the readability of the code is not impaired much at all by that one extra line is it?

To sum up, I would go with variant 2 unless the loop was an inner loop that had to be tight, in which case I would go with variant 1 just to be sure.

And of course if elements are added to arr inside the loop and the loop needs to cover those elements then only the second variant will be correct.

like image 157
Michael Slade Avatar answered Oct 20 '22 13:10

Michael Slade


I would suggest if is possible for you use iterators instead of indices. e.g:

In c++:

for( const_iterator it = arr.begin(), ite = arr.end();
     it != ite; ++it)
{
 ....
}

In c#:

foreach(var item in arr){....}

One of the advantages in c++ is when you have list instead of vector, in vector size() is O(1) but in list it's O(n). Also this prevents from situations which calls, arr.Size() too many times.

General advantage is more readable codes in both c# and c++ but still there are some situations that you can't use them, and you should use indices.

like image 40
Saeed Amiri Avatar answered Oct 20 '22 14:10

Saeed Amiri


Second option is better:

for(int i=0; i<arr.size(); ++i) {//print the values}

the variable i will be release after the loop is over. arr.size() will be calculated once the loop is initialized. Memory will be not assigned to store arr_size variable.

like image 1
Romil Kumar Jain Avatar answered Oct 20 '22 14:10

Romil Kumar Jain