Reading some examples of range based loops they suggest two main ways 1, 2, 3, 4
std::vector<MyClass> vec;
for (auto &x : vec)
{
// x is a reference to an item of vec
// We can change vec's items by changing x
}
or
for (auto x : vec)
{
// Value of x is copied from an item of vec
// We can not change vec's items by changing x
}
Well.
When we don't need changing vec
items, IMO, Examples suggest to use second version (by value). Why they don't suggest something which const
references (At least I have not found any direct suggestion):
for (auto const &x : vec) // <-- see const keyword
{
// x is a reference to an const item of vec
// We can not change vec's items by changing x
}
Isn't it better? Doesn't it avoid a redundant copy in each iteration while it's a const
?
Then they give a wrong suggestion.
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 anint
is not expensive, creating a copy is basically equivalent to (if not more efficient than) having an observingconst &
.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 &
.If you don't want to change the items as well as want to avoid making copies, then
auto const &
is the correct choice: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.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):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 usingauto const &
as the variable in a range based for loop instead of justauto &
.If you have a
std::vector<int>
orstd::vector<double>
, then it's just fine to useauto
(with value copy) instead ofconst auto&
, since copying anint
or adouble
is cheap:But if you have a
std::vector<MyClass>
, whereMyClass
has some non-trivial copy semantics (e.g.std::string
, some complex custom class, etc.) then I'd suggest usingconst auto&
to avoid deep-copies: