The book i am reading offers this example when iterating over a vector
for (auto &e: v) {
cout << e << endl;
}
Suppose v is declared as vector<int> v
, in other words, we know that the type of elements inside this collection is int
.
Is using auto
in any way better or preferred to?
for (int &e: v) {
cout << e << endl;
}
Why?
Yes. auto
is preferred. Because if you change the declaration ofv
from:
std::vector<int> v; //before
to this:
std::vector<float> v; //after
If you use int &
in the for
, then you have to change that as well. But with auto
, no need to change!
In my opinion, working with auto
is more or less like programming to interface. So if you do an operation +=
in the loop, and you don't really care about the type of the loop variable e
as long as the type supports +=
operation, then auto
is the solution:
for(auto & e : v)
{
e += 2;
}
In this example, all you care about that the type of e
supports +=
with int
on the right hand side. It will work even for user-defined types, which has defined operator+=(int)
, or operator+=(T)
where T
is a type which supports implicit conversion from int
. It is as if you're programming to interface:
std::vector<Animal*> animals;
animals.push_back(new Dog());
animals.push_back(new Cat());
animals.push_back(new Horse());
for(size_t i = 0 ; i < animals.size(); ++i)
{
animals[i]->eat(food); //program to interface
}
Of course, you would like to write this loop as:
for(Animal * animal : animals)
{
animal->eat(food); //still program to interface
}
Or simply this:
for(auto animal : animals)
{
animal->eat(food); //still program to interface
}
It is still programming to interface.
But at the same time, the point in @David's comment is worth noting.
On your first example, you have less dependency on what the elements of the vector are.
Suppose that in a month, you require that your vector stores larger integers, so you will have to use an std::vector<int64_t>
, or some other, wider type. Now all of the code that iterates over that vector is invalid. You'll have to modify each:
for (int &e: v) {}
For a:
for (int64_t &e: v) {}
That is why it's better to just let auto
deduce the internal type. That way you can modify the type stored in your vector for another, compatible one, and all your code will still work.
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