Reputation: 1339
In C++11, I can iterate over some container like so:
for(auto i : vec){
std::cout << i << std::endl;
}
But I know that this needlessly - needlessly, since I only need to print the values of vec
- makes a copy of (EDIT: each element of) vec
, so instead I could do:
for(auto &i : vec){
std::cout << i << std::endl;
}
But I want to make sure that the values of vec
are never modified and abide by const-correctness, so I can do:
for(const auto &i : vec){
std::cout << i << std::endl;
}
So my question is: If I only need to look at the values of some container, wouldn't the very last loop (const auto &i
) always be preferred due to the increased effieciency of not having an extra copy of (EDIT: each element of) vec
?
I have a program that I'm developing in which I'm considering making this change throughout, since efficiency is critical in it (the reason I'm using C++ in the fist place).
Upvotes: 70
Views: 51241
Reputation: 122133
Disclaimer: In general the difference between auto
and auto&
is subtle, partly a matter of style, but sometimes also a matter of correctness. I am not going to cover the general case here!
In a range based for loop, the difference between
for (auto element : container) {}
and
for (auto& element_ref : container) {}
is that element
is a copy of the elements in the container
, while element_ref
is a reference to the elements in the container.
To see the difference in action, consider this example:
#include <iostream>
int main(void) {
int a[5] = { 23,443,16,49,66 };
for (auto i : a) i = 5;
for (const auto& i : a) std::cout << i << std::endl;
for (auto& i : a) i = 5;
for (const auto& i : a) std::cout << i << std::endl;
}
It will print
23
443
16
49
66
5
5
5
5
5
because the first loop works on copies of the array elements, while the second actually modifies the elements in the array.
If you dont want to modify the elements then often a const auto&
is more appropriate, because it avoids copying the elements (which can be expensive).
Upvotes: 7
Reputation: 387
Imagine if your vector contains strings. Long strings. 5000 long strings. Copy them unnecessarily and you end up with a nicely written for loop that is awfully inefficient.
Make sure your code follows your intention. If you do not need a copy inside of the loop, do not make one.
Use a reference & as suggested above, or iterators.
Upvotes: 1
Reputation: 503805
Yes. The same reason if you only ever read an argument you make the parameter const&
.
T // I'm copying this
T& // I'm modifying this
const T& // I'm reading this
Those are your "defaults". When T
is a fundamental type (built-in), though, you generally just revert to const T
(no reference) for reading, because a copy is cheaper than aliasing.
I have a program that I'm developing in which I'm considering making this change throughout, since efficiency is critical in it
Upvotes: 95