In terms of performance, what would work faster? Is there a difference? Is it platform dependent?
//1. Using vector<string>::iterator: vector<string> vs = GetVector(); for(vector<string>::iterator it = vs.begin(); it != vs.end(); ++it) { *it = "Am I faster?"; } //2. Using size_t index: for(size_t i = 0; i < vs.size(); ++i) { //One option: vs.at(i) = "Am I faster?"; //Another option: vs[i] = "Am I faster?"; }
A std::vector can never be faster than an array, as it has (a pointer to the first element of) an array as one of its data members. But the difference in run-time speed is slim and absent in any non-trivial program. One reason for this myth to persist, are examples that compare raw arrays with mis-used std::vectors.
Iterators aren't intended to be faster, they're intended to be as fast, which they are, and significantly more generic.
Iterator and for-each loop are faster than simple for loop for collections with no random access, while in collections which allows random access there is no performance change with for-each loop/for loop/iterator.
Using a sorted vector instead of a set gives you faster lookup and much faster iteration, but at the cost of slower insertion. Insertion into a set, using set::insert, is proportional to log N, but insertion into a sorted vector, using insert_into_vector, is proportional to N.
Using an iterator results in incrementing a pointer (for incrementing) and for dereferencing into dereferencing a pointer.
With an index, incrementing should be equally fast, but looking up an element involves an addition (data pointer+index) and dereferencing that pointer, but the difference should be marginal.at()
also checks if the index is within the bounds, so it could be slower.
Benchmark results for 500M iterations, vector size 10, with gcc 4.3.3 (-O3), linux 2.6.29.1 x86_64:at()
: 9158msoperator[]
: 4269msiterator
: 3914ms
YMMV, but if using an index makes the code more readable/understandable, you should do it.
With modern compilers, all options are practically free, but iterators are very slightly better for iterating and easier to use with range-for loops (for(auto& x: vs)
).
Code:
#include <vector> void iter(std::vector<int> &vs) { for(std::vector<int>::iterator it = vs.begin(); it != vs.end(); ++it) *it = 5; } void index(std::vector<int> &vs) { for(std::size_t i = 0; i < vs.size(); ++i) vs[i] = 5; } void at(std::vector<int> &vs) { for(std::size_t i = 0; i < vs.size(); ++i) vs.at(i) = 5; }
The generated assembly for index()
and at()
is identical godbolt, but the loop setup for iter()
is two instructions shorter:
iter(std::vector<int, std::allocator<int> >&): mov rax, QWORD PTR [rdi] mov rdx, QWORD PTR [rdi+8] cmp rax, rdx je .L1 .L3: ; loop body mov DWORD PTR [rax], 5 add rax, 4 cmp rax, rdx jne .L3 .L1: ret index(std::vector<int, std::allocator<int> >&): mov rax, QWORD PTR [rdi] mov rdx, QWORD PTR [rdi+8] sub rdx, rax mov rcx, rdx shr rcx, 2 je .L6 add rdx, rax .L8: ; loop body mov DWORD PTR [rax], 5 add rax, 4 cmp rdx, rax jne .L8 .L6: ret
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With