Reputation:
So according to n2243 the range-based for loop is equivalent to this:
{
auto && __range = ( expression );
for ( auto __begin = std::Range<_RangeT>::begin(__range),
__end = std::Range<_RangeT>::end(__range);
__begin != __end;
++__begin )
{
for-range-declaration = *__begin;
statement
}
}
It then says 2 If the header <iterator_concept> is not included prior to a use of the range-based for statement, the program is ill-formed.
so I question how up to date this is. I'm also curious what std::Range
is or if it's purely an implementation detail. The closest I can find is n3350.
This answer relies on this information and says:
Range for is as fast as possible since it caches the end iterator[citation], 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).
P.S. 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.
I'm curious if it actually makes a difference now. As far as I can see it's just syntactic sugar. For example, in a loop where you could do auto it = s.rbegin(); it != s.rend(); ++it
, it would require boiler plate code that returns reverse iterators where the ranged-based for loop expects begin
and end
. And if all it saves is typing, then what other advantages does it offer, since it only expects begin
and end
? I'm curious if the answer I quoted above still holds weight since the paper is from 2007.
Upvotes: 4
Views: 2105
Reputation: 42554
As @DyP says, this section has changed a bit in the final standard. C++11 6.5.4 The range-based for
statement [stmt.ranged]:
1 For a range-based
for
statement of the formfor ( 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 formfor ( 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 } }
where
__range
,__begin
, and__end
are variables defined for exposition only, and_RangeT
is the type of the expression, and begin-expr and end-expr are determined as follows:
if
_RangeT
is an array type, begin-expr and end-expr are__range
and__range + __bound
, respectively, where__bound
is the array bound. If_RangeT
is an array of unknown size or an array of incomplete type, the program is ill-formed;if
_RangeT
is a class type, the unqualified-idsbegin
andend
are looked up in the scope of class_RangeT
as if by class member access lookup (3.4.5), and if either (or both) finds at least one declaration, begin-expr and end-expr are__range.begin()
and__range.end()
, respectively;otherwise, begin-expr and end-expr are
begin(__range)
andend(__range)
, respectively, wherebegin
andend
are looked up with argument-dependent lookup (3.4.2). For the purposes of this name lookup, namespacestd
is an associated namespace.[ Example:
int array[5] = { 1, 2, 3, 4, 5 }; for (int& x : array) x *= 2;
—end example ]
2 In the decl-specifier-seq of a for-range-declaration, each decl-specifier shall be either a type-specifier or
constexpr
.
Upvotes: 3