这看起来似乎是一个奇怪的问题,但我今天正在和一位朋友谈话,他们正在抨击今天的C ++程序员以及他们如何做得不对。他说他的主要问题是滥用迭代,代码如下:
for(int i = 0; i<((int) someVector.size()); ++i){
//Something here
}
而不是更传统的
vector::iterator i;
for(i = someVector.begin(); i!=someVector.end(); ++i){
//Something here
}
虽然我理解这两种方法,但是为什么第二种优于第一种方法有什么特别的原因吗?是性能吗?还是其他一些因素?
提前致谢。
答案 0 :(得分:3)
这些都不是好风格。
第一个有无用且危险的演员。
第二个允许迭代变量泄漏到循环范围之外,并且不使用相等测试,并且在迭代器上使用后增量,这会产生无用的副本。
更好的是:
using std::begin, std::end;
for( auto it = begin(container), end_it = end(container); it != end_it; ++it )
这适用于任何STL容器,数组以及您使用begin
和end
辅助函数提供的任何容器。
答案 1 :(得分:1)
对于vector
,两者之间几乎没有差别。但是,如果你想迭代一个没有随机访问的set
数据结构,那么使用迭代器的第二个选项将是唯一明智的选择。
C ++标准库努力使“迭代器”接口尽可能地与许多不同类型的容器保持一致。
答案 2 :(得分:0)
在某些数据结构中,计算大小可能效率低下。根据优化器可以执行的操作,实际上最终可能会为循环的每次迭代调用size()方法。当你使用第二个代码段时,你不依赖于调用一个方法来计算大小,当你真正想要的是知道你是否已经到达目的地时。
例如,考虑一个链表。除非链表被设计为在内部保持计数,否则您必须遍历整个列表以查找大小。此外,对于数据结构,无法使用索引来获取值。在这种情况下,您必须使用正确的迭代器方法。
答案 3 :(得分:0)
使用迭代器通常没有真正的性能提升。可能更少。但是,与迭代的“C方法”相比,它们具有一些潜在的优势:
1)通过迭代器抽象容器可能更容易。由于我们每次迭代都处理一个指针,如果容器类型需要通过表单中的索引更改来更改和访问元素(或者甚至不可能因为随机访问是不可能的),迭代器可以节省一些繁琐的编辑。 / p>
2)您可以避免每次迭代使用size()
。虽然你可以预先计算一次,但完全避免它仍然更好。
3)你基本上处理指向你正在迭代的容器中每个元素的指针。这更好(嗯,至少对我而言),并且可能比索引更紧凑。
答案 4 :(得分:0)
首先,我注意到大多数代码都不应该有明确的循环。如果您要对集合进行操作,则应使用算法。如果其中一个标准算法不能完成这项工作,你通常应该仍然实现你需要的算法,然后在需要的地方应用该算法(但如果你开始注意,你可能会惊讶于标准算法将起作用。)
如果确实需要编写显式循环,请考虑使用基于范围的循环:
for (auto i : someVector)
// ...
然而,大多数情况下,这应该是在算法的实现中。