我想知道使用迭代器相对于数组索引的主要优点是什么。我已经谷歌过了,但没有找到正确的答案。
我想你是在谈论使用向量时,对吧?
主要优点是迭代器代码适用于所有STL容器,而数组索引运算符[]
仅适用于向量和双端队列。这意味着您可以自由更改底层容器(如果需要),而无需重新编写每个循环。这也意味着您可以将迭代代码放入模板中,它将适用于任何容器,而不仅仅是双端队列和向量(当然还有数组)。
所有标准容器都提供了迭代器概念。迭代器知道如何在容器中查找下一个元素,特别是在底层结构不像数组时。并非每个容器都提供类似于数组的 operator[]
,因此养成使用迭代器的习惯将使代码看起来更加一致,无论你选择哪种容器。
您可以将集合实现抽象化。
对之前的回答进行进一步扩展:
使用operator[]编写循环会限制您使用支持[]并使用相同索引/大小类型的容器。否则,您需要重写每个循环以更改容器。
即使您的容器支持[],它也可能不是顺序遍历的最佳选择。[]基本上是一个随机访问运算符,对于向量而言是O(1),但根据底层容器的不同,可能会达到O(n)。
这只是一个小问题,但如果您使用迭代器,您的循环可以更轻松地转换为使用标准算法,例如std::for_each。
有许多数据结构,例如哈希表和链表不能被自然或快速地索引,但它们确实是可遍历的。迭代器充当一个接口,让您在不知道源代码实际实现的情况下遍历任何数据结构。
transform
和for_each
。它们不接受索引,而是使用迭代器。迭代器有助于隐藏容器实现,使程序员更专注于算法。 for_each
函数可应用于支持前向迭代器的任何内容。operator[]
相比),因为它们本质上是通过指针进行迭代。如果你做这样的事情:for (int i = 0; i < 10; ++i)
{
my_vector[i].DoSomething();
}
循环的每次迭代都不必要地计算my_vector.begin() + i
。如果使用迭代器,增加迭代器意味着它已经指向下一个元素,因此您不需要进行额外的计算。这是一件小事,但在紧密的循环中可能会产生差异。
+
很少会花费很多周期。 - kennytm另一个微小的区别是,您不能按索引在向量中使用erase()删除元素,必须具有迭代器。这并不是什么大问题,因为您始终可以将“vect.begin() + index”作为迭代器,但还有其他考虑因素。例如,如果您这样做,则必须始终将索引与size()进行比较,而不是某个变量分配了该值。
所有这些都不值得太多担心,但如果可以选择,我更喜欢迭代器访问,原因已经说明了这一点。
我认为这更多是一致性和代码重用的问题。
最后,我想说即使C
数组也有迭代器。
const Foo* someArray = //...
const Foo* otherArray = new Foo[someArrayLength];
std::copy(someArray, someArray + someArrayLength, otherArray);
iterator_traits
类已经被特化,以便于指针或模型RandomAccessIterator
。
[]
也可以应用于映射/无序映射。 ;) - kennytm[]
(或at
)提供的内容。 - T.E.D.operator[]
会让用户的操作变得更加困难。你应该阅读STL-Concepts以了解其中的区别。 - Björn Pollex