Summary
In this post, I will introduce auto, const auto, auto&, const auto&, auto&&, and const auto&&.
Conclusion
We provide the conclusion first.
- When you want a read-only access (generic or non-generic codes), use
auto const &, which will give you a reference rather than a copy. - When you want a read-write access in generic codes, use
auto &&. - When you want a read-write access in non-generic codes, use
auto &.
Details
auto
Auto will create a copy of each element in the range so use this variant when you want to work with a copy.
Note the following situations.
1. Containers return proxy objects upon dereferencing of their iterators.
std::vector<bool> vec{false, false, false};
for (auto x : vec) {
x = true; // now vec is {true, true, true}
}
const auto
It will provide an immutable copy of each element.
However we should avoid using const auto because there is no reason we create a copy. Thus, use const auto & instead.
const auto& or auto const &
This is the number one choice for iterating over a range when all you want to is read its elements. No copies are made and the compiler can verify that you indeed do not modify the elements.
auto&
Use auto& when you want to modify elements in the range in non-generic codes. & means it will make references to the original elements in the range. See special situations (eg, inside templates) in reference.
auto&&
Use auto&& when you want to modify elements in the range in generic codes. Actually it also works in non-generic codes, but it unnecessarily confuses people. Details are in reference.
const auto&&
There is no reason for choosing this variant over const auto&.
Reference
See this blog for more details and some special situations.