Reading various questions here on Stack Overflow about C++ iterators and performance**, I started wondering if for(auto& elem : container)
gets "expanded" by the compiler into the best possible version? (Kind of like auto
, which the compiler infers into the right type right away and is therefore never slower and sometimes faster).
** For example, does it matter if you write
for(iterator it = container.begin(), eit = container.end(); it != eit; ++it)
or
for(iterator it = container.begin(); it != container.end(); ++it)
for non-invalidating containers?
To loop through a set of code a specified number of times, we can use the range() function, The range() function returns a sequence of numbers, starting from 0 by default, and increments by 1 (by default), and ends at a specified number.
Range-based for loop in C++ is added since C++ 11. It executes a for loop over a range. Used as a more readable equivalent to the traditional for loop operating over a range of values, such as all elements in a container.
Generally, the for loop can be more efficient than the while loop, but not always. The idea of the While loop is: While something is the case, do the following block of code. In this code, we have defined a variable name condition, and condition starts at a value of 1.
The "for" loop For loops can iterate over a sequence of numbers using the "range" and "xrange" functions. The difference between range and xrange is that the range function returns a new list with numbers of that specified range, whereas xrange returns an iterator, which is more efficient.
The Standard is your friend, see [stmt.ranged]/1
For a range-based for statement of the form
for ( for-range-declaration : expression ) statement
let range-init be equivalent to the expression surrounded by parentheses
( expression )
and for a range-based for statement of the form
for ( for-range-declaration : braced-init-list ) statement
let range-init be equivalent to the braced-init-list. In each case, a range-based
for
statement is equivalent to{ auto && __range = range-init; for ( auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } }
So yes, the Standard guarantees that the best possible form is achieved.
And for a number of containers, such as vector
, it is undefined behavior to modify (insert/erase) them during this iteration.
Range-for is as fast as possible since it caches the end iterator[citation provided], uses pre-increment and only dereferences the iterator once.
so if you tend to write:
for(iterator i = cont.begin(); i != cont.end(); i++) { /**/ }
Then, yes, range-for may be slightly faster, since it's also easier to write there's no reason not to use it (when appropriate).
N.B. I said it's as fast as possible, it isn't however faster than possible. You can achieve the exact same performance if you write your manual loops carefully.
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