【发布时间】:2012-08-18 12:31:59
【问题描述】:
我正在阅读的这本书在迭代 vector 时提供了这个示例
for (auto &e: v) {
cout << e << endl;
}
假设v被声明为vector<int> v,换句话说,我们知道这个集合中元素的类型是int。
使用auto 是否更好或更喜欢?
for (int &e: v) {
cout << e << endl;
}
为什么?
【问题讨论】:
我正在阅读的这本书在迭代 vector 时提供了这个示例
for (auto &e: v) {
cout << e << endl;
}
假设v被声明为vector<int> v,换句话说,我们知道这个集合中元素的类型是int。
使用auto 是否更好或更喜欢?
for (int &e: v) {
cout << e << endl;
}
为什么?
【问题讨论】:
是的。 auto 是首选。因为如果你把v的声明从:
std::vector<int> v; //before
到这里:
std::vector<float> v; //after
如果您在for 中使用int &,那么您也必须更改它。但是有了auto,就不用改了!
在我看来,使用auto 或多或少类似于programming to interface。所以如果你在循环中做了一个操作+=,而你并不真正关心循环变量e的类型,只要类型支持+=操作,那么auto就是解决方案:
for(auto & e : v)
{
e += 2;
}
在这个例子中,你只关心e 的类型支持+= 和右侧的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 评论中的观点值得注意。
【讨论】:
float& 设置int&,而不是编译器静默接受本应使用的代码ints...并不是说拥有int& 是一个更好的主意,这完全取决于您在for 循环的主体中所做的事情,如果它不依赖于确切的类型auto 会更好
int 更改为float 在这种情况下auto 是一个更好的解决方案。
auto& 会做......但我还不习惯没有明确的类型:)(除非我真的不想知道!)
for (int &e: v) 将不会编译。请注意,它是int & e,而不仅仅是int e。但是,for (int e: v) 将编译。
在您的第一个示例中,您对向量元素的依赖较少。
假设在一个月内,您需要向量存储更大的整数,因此您将不得不使用std::vector<int64_t> 或其他更宽的类型。现在,遍历该向量的所有代码均无效。您必须修改每个:
for (int &e: v) {}
对于一个:
for (int64_t &e: v) {}
这就是为什么最好让auto 推断内部类型。这样,您可以将存储在向量中的类型修改为另一个兼容的类型,并且您的所有代码仍然可以工作。
【讨论】: