This may seem frivolous to some of you, but which of the following 2 methods of iteration over a STL container is better? Why?
Method 0, for several reasons.
Of course, the best solution will often be solution 2: One of the std algorithms. std::for_each, std::transform, std::copy or whatever else you need. This has some further advantages:
In general, avoid overspecifying your code. Specify exactly what you want done, and nothing else. The std algorithms are usually the way to go there, but even without them, if you don't need the index i
, why have it? Use iterators instead, in that case.
Method 0 is faster and therefore recommended.
Method 1 uses size() which is allowed to be O(1), depending on the container and the stl implementation.
It depends on which type of container. For a vector
, it probably doesn't matter which you use. Method 0 has become more idiomatic, but their isn't a big difference, as everyone says.
If you decided to use a list
, instead, method 1 would, in principle, be O(N)
, but in fact there is no list at()
method, so you can't even do it that way. (So at some level your question stacks the deck.)
But that in itself is another argument for method 0: it uses the same syntax for different containers.
If you don't mind a (very?) small loss of efficiency, i'd recommend using Boost.Foreach
BOOST_FOREACH( Elem& e, elemVec )
{
// Your code
}
Coincidentally I made a speed test recently (filling 10 * 1024 * 1024 ints with rand() ).
These are 3 runs, time in nano-seconds
vect[i] time : 373611869
vec.at(i) time : 473297793
*it = time : 446818590
arr[i] time : 390357294
*ptr time : 356895778
UPDATE : added stl-algorithm std::generate, which seems to run the fastest, because of special iterator-optimizing (VC++2008). time in micro-seconds.
vect[i] time : 393951
vec.at(i) time : 551387
*it = time : 596080
generate = time : 346591
arr[i] time : 375432
*ptr time : 334612
Conclusion : Use standard-algorithms, they might be faster than a explicit loop ! (and also good practice)
Update : the above times were in a I/O-bound situation, I did the same tests with a CPU-bound (iterate over a relatively short vector, which should fit in cache repeatedly, multiply each element by 2 and write back to vector)
//Visual Studio 2008 Express Edition
vect[i] time : 1356811
vec.at(i) time : 7760148
*it = time : 4913112
for_each = time : 455713
arr[i] time : 446280
*ptr time : 429595
//GCC
vect[i] time : 431039
vec.at(i) time : 2421283
*it = time : 381400
for_each = time : 380972
arr[i] time : 363563
*ptr time : 365971
Interestingly iterators and operator[] is considerably slower in VC++ compared to for_each (which seems to degrade the iterators to pointers through some template-magic for performance).
In GCC access times are only worse for at(), which is normal, because it's the only range-checked function of the tests.
The first version works with any container and so is more useful in template functions that take any container a s a parameter. It is also conceivably slightly more efficient, even for vectors.
The second version only works for vectors and other integer-indexed containers. It'd somewhat more idiomatic for those containers, will be easily understood by newcomers to C++, and is useful if you need to do something else with the index, which is not uncommon.
As usual, there is no simple "this one is better" answer, I'm afraid.