我正在阅读的这本书在迭代一个vector
for (auto &e: v) {
cout << e << endl;
}
假设 v 被声明为vector<int> v
,换句话说,我们知道这个集合中元素的类型是int
。
是否auto
以任何方式更好或更喜欢使用?
for (int &e: v) {
cout << e << endl;
}
为什么?
是的。auto
是首选。因为如果您更改v
from 的声明:
std::vector<int> v; //before
对此:
std::vector<float> v; //after
如果你int &
在 中使用for
,那么你也必须改变它。但是有了auto
,就不需要改变了!
在我看来,使用 withauto
或多或少类似于对 interface 进行编程。因此,如果您+=
在循环中进行操作,并且您并不真正关心循环变量的类型e
,只要类型支持+=
操作,那么auto
解决方案是:
for(auto & e : v)
{
e += 2;
}
在此示例中,您只关心右侧的e
支撑类型。它甚至适用于已定义的用户定义类型,或者 where是支持隐式转换的类型。就好像您正在编程接口:+=
int
operator+=(int)
operator+=(T)
T
int
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
}
当然,你想把这个循环写成:
for(Animal * animal : animals)
{
animal->eat(food); //still program to interface
}
或者简单地说:
for(auto animal : animals)
{
animal->eat(food); //still program to interface
}
它仍在编程接口。
但与此同时,@David 评论中的要点值得注意。
在您的第一个示例中,您对向量元素的依赖程度较低。
假设在一个月内,您需要向量存储更大的整数,因此您将不得不使用std::vector<int64_t>
或其他更宽的类型。现在所有迭代该向量的代码都是无效的。您必须修改每个:
for (int &e: v) {}
为一个:
for (int64_t &e: v) {}
这就是为什么最好只auto
推断内部类型。这样,您可以将存储在向量中的类型修改为另一个兼容的类型,并且您的所有代码仍然可以工作。