Question about iterator loops

Say I have a vector of ints, and I want to print each of them using an iterator loop. The first way I've seen this done is like this:

1
2
3
4
5
std::vector<int> myVector = {1, 2, 3, 4, 5};
for (auto it = myVector.begin(); it != myVector.end(); ++it)
{
    std::cout << *it << std::endl;
}


And the second way is this:

1
2
3
4
5
std::vector<int> myVector = {1, 2, 3, 4, 5};
for (auto it = myVector.begin(), end = myVector.end(); it != end; ++it)
{
    std::cout << *it << std::endl;
}


Which way is better? Does the first one create an iterator to myVector.end() every time it loops, or does it somehow stay in memory? If it does stay in memory, does that make the first one better than the second?
http://stackoverflow.com/questions/795987/c-iterators-loop-optimization?lq=1
http://stackoverflow.com/questions/15433381/performance-of-piter-cont-end-in-for-loop

Basically it should make almost no difference as long as your compiler isn't 20 years old. It will end up caching/optimizing it all away anyway. Always worth checking if you want a perfect answer for your environment though.

In any event, I think the choice between the two versions should be primarily based on grounds of readability. Without profiling data, micro-optimizations like this to me look premature.

Sums up my feelings on the matter.
In which case the C++11 version is my answer for this.

for(auto i: myVector) { }
I always prefer the old style:

for(typename std::vector<type>::const_iterator it{vec.begin()}; it != vec.end(); ++it) cout<< *it<< endl;

It's about readability, but in this case you have two choices.
Last edited on
If there is a difference it will probably be very small and not worth thinking about. If you later find out this is a bottleneck you can always go back and change it later, but that is unlikely because the code inside the loop body is taking up most of the loop time anyway (unless you are doing something very simple).

If I had to choose between the two ways in the OP I would go for what is simpler/more readable which in my opinion is the first one.
Last edited on
In
1
2
3
4
for (auto it = myVector.begin(); it != myVector.end(); ++it) 
{
     // code does not resize the vector
}

myVector.end() is a loop-invariant: the typical C++ optimiser would identify this as a loop-invariant and hoist it.
https://en.wikipedia.org/wiki/Loop-invariant_code_motion

This is typical:
1
2
3
4
5
6
7
8
#include <vector>

int foo( const std::vector<int>& vec )
{
    int sum = 0 ;
    for( auto it = vec.begin() ; it != vec.end(); ++it ) sum += *it ;
    return sum ;
}


foo(std::vector<int, std::allocator<int> > const&):
    
	mov	rdx, QWORD PTR [rdi] ; move vec.begin() to 'it' (hold 'it' in register rdx)
	mov	rcx, QWORD PTR [rdi+8] ; move vec.end() to register rcx
	
	xor	eax, eax ; set 'sum' to zero (hold 'sum' in register eax)
	
	cmp	rdx, rcx ; compare it with vec.end()
	je	.L4 ; if equal, goto end (label L4)
.L3:
	add	eax, DWORD PTR [rdx] ; sum += *it
	add	rdx, 4 ; ++it
	cmp	rcx, rdx ; compare it with vec.end()
	jne	.L3 ; if not equal, goto beginning of loop (label L3)
	rep ret
.L4:
	rep ret

http://goo.gl/6yTJ86

Performance being the same, essentially there are a few other things to consider.

Readability: how easy is it to understand the code
Correctness: can we minimise the chance of programming errors
Fragility: would we have to modify our code if something else changes?
(For instance, the type of the sequence is changed - from a vector to a list; to an array; to some user-defined sequence.)

On all counts this is the winner: for( const auto& v : seq ) { /* code does not resize the sequence */ }

This would be a close runner up : for( auto it = std::begin(seq) ; it != std::end(seq); ++it ) { ... }
Topic archived. No new replies allowed.