Range-based for loop in C++ 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.
C++11 introduced the ranged for loop. This for loop is specifically used with collections such as arrays and vectors. Here, the ranged for loop iterates the array num from beginning to end. The int variable var stores the value of the array element in each iteration.
C++ auto auto, const, and references The auto keyword by itself represents a value type, similar to int or char . It can be modified with the const keyword and the & symbol to represent a const type or a reference type, respectively. These modifiers can be combined.
Range-Based 'for' loops have been included in the language since C++11. It automatically iterates (loops) over the iterable (container). This is very efficient when used with the standard library container (as will be used in this article) as there will be no wrong access to memory outside the scope of the iterable.
If you don't want to change the items as well as want to avoid making copies, then auto const &
is the correct choice:
for (auto const &x : vec)
Whoever suggests you to use auto &
is wrong. Ignore them.
Here is recap:
auto x
when you want to work with copies.auto &x
when you want to work with original items and may modify them.auto const &x
when you want to work with original items and will not modify them.If you have a std::vector<int>
or std::vector<double>
, then it's just fine to use auto
(with value copy) instead of const auto&
, since copying an int
or a double
is cheap:
for (auto x : vec)
....
But if you have a std::vector<MyClass>
, where MyClass
has some non-trivial copy semantics (e.g. std::string
, some complex custom class, etc.) then I'd suggest using const auto&
to avoid deep-copies:
for (const auto & x : vec)
....
When we don't need changing
vec
items, Examples suggest to use first version.
Then they give a wrong suggestion.
Why they don't suggest something which const references
Because they give a wrong suggestion :-) What you mention is correct. If you only want to observe an object, there is no need to create a copy, and there is no need to have a non-const
reference to it.
EDIT:
I see the references you link all provide examples of iterating over a range of int
values or some other fundamental data type. In that case, since copying an int
is not expensive, creating a copy is basically equivalent to (if not more efficient than) having an observing const &
.
This is, however, not the case in general for user-defined types. UDTs may be expensive to copy, and if you do not have a reason for creating a copy (such as modifying the retrieved object without altering the original one), then it is preferable to use a const &
.
I'm going to be contrary here and say there is no need for auto const &
in a range based for loop. Tell me if you think the following function is silly (not in its purpose, but in the way it is written):
long long SafePop(std::vector<uint32_t>& v)
{
auto const& cv = v;
long long n = -1;
if (!cv.empty())
{
n = cv.back();
v.pop_back();
}
return n;
}
Here, the author has created a const reference to v
to use for all operations which do not modify v. This is silly, in my opinion, and the same argument can be made for using auto const &
as the variable in a range based for loop instead of just auto &
.
I would consider
for (auto&& o : range_expr) { ...}
or
for (auto&& o : std::as_const(range_expr)) { ...}
it always works.
and beware of possible Temporary range expression pitfalls.
In C++20 you have something like
for (T thing = foo(); auto& x : thing.items()) { /* ... */ }
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