以下面两行代码为例:

for (int i = 0; i < some_vector.size(); i++)
{
    //do stuff
}

这:

for (some_iterator = some_vector.begin(); some_iterator != some_vector.end();
    some_iterator++)
{
    //do stuff
}

有人告诉我第二种方法更可取。为什么会这样呢?


当前回答

我总是使用数组索引,因为我的许多应用程序需要“显示缩略图图像”之类的东西。所以我写了这样的东西:

some_vector[0].left=0;
some_vector[0].top =0;<br>

for (int i = 1; i < some_vector.size(); i++)
{

    some_vector[i].left = some_vector[i-1].width +  some_vector[i-1].left;
    if(i % 6 ==0)
    {
        some_vector[i].top = some_vector[i].top.height + some_vector[i].top;
        some_vector[i].left = 0;
    }

}

其他回答

只有当vector.size()是一个快速操作时,第一种形式才有效。这对于向量是正确的,但是对于列表就不是这样了。另外,您计划在循环体中做什么?如果您计划访问元素,如

T elem = some_vector[i];

然后假设容器定义了operator[](std::size_t)。同样,这适用于vector容器,但不适用于其他容器。

迭代器的使用使您更接近容器独立性。您没有假设随机访问能力或快速size()操作,只是假设容器具有迭代器功能。

您可以通过使用标准算法进一步增强代码。根据你想要实现的目标,你可以选择使用std::for_each(), std::transform()等等。通过使用标准算法而不是显式循环,您可以避免重新发明轮子。您的代码可能更高效(如果选择了正确的算法)、正确和可重用。

我不认为这对向量有多大区别。我更喜欢自己使用索引,因为我认为它更具可读性,你可以做随机访问,如向前跳转6个项目或向后跳转,如果需要的话。

我还喜欢像这样引用循环内的项目,这样在位置周围就不会有很多方括号:

for(size_t i = 0; i < myvector.size(); i++)
{
    MyClass &item = myvector[i];

    // Do stuff to "item".
}

使用迭代器可以很好,如果你认为你可能需要在未来的某个时候用一个列表替换向量,它也看起来更时尚的STL怪胎,但我想不出任何其他原因。

已经有几个好观点了。我还有一些补充意见:

Assuming we are talking about the C++ standard library, "vector" implies a random access container that has the guarantees of C-array (random access, contiguos memory layout etc). If you had said 'some_container', many of the above answers would have been more accurate (container independence etc). To eliminate any dependencies on compiler optimization, you could move some_vector.size() out of the loop in the indexed code, like so: const size_t numElems = some_vector.size(); for (size_t i = 0; i Always pre-increment iterators and treat post-increments as exceptional cases.

for (some_iterator = some_vector.begin(); some_iterator != some_vector.end(); ++some_iterator){ //do stuff }

假设和可索引std::vector<>类似于容器,没有好的理由选择一个而不是另一个,按顺序遍历容器。如果必须频繁引用较旧或较新的元素索引,则使用索引版本更合适。

一般来说,使用迭代器是首选的,因为算法会使用它们,并且可以通过改变迭代器的类型来控制(并隐式记录)行为。数组位置可以用来代替迭代器,但是语法上的差异会很明显。

比“告诉CPU做什么”(命令式)更好的是“告诉库你想要什么”(函数式)。

因此,你应该学习stl中的算法,而不是使用循环。

分离关注点

将迭代代码从循环的“核心”关注点中分离出来是非常好的。这几乎是一个设计决策。

实际上,通过索引迭代将您与容器的实现联系在一起。向容器请求开始和结束迭代器,使循环代码可用于其他容器类型。

同样,在std::for_each方法中,你告诉集合要做什么,而不是询问它的内部信息

0x标准将引入闭包,这将使这种方法更容易使用-看看例如Ruby的[1..6]的表达能力。每个{|i| print i;}……

性能

但是可能有一个被监督的问题是,使用for_each方法产生了一个并行迭代的机会——intel线程块可以将代码块分布在系统中的处理器数量上!

注意:在发现算法库,特别是foreach之后,我花了两三个月的时间写了非常小的“helper”操作符结构,这会让其他开发人员发疯。在这之后,我回到了一个实用的方法-小循环体不应该再有foreach了:)

关于迭代器的必读参考书是《扩展STL》。

GoF在迭代器模式的末尾有一小段话,讲的是这种迭代;它被称为“内部迭代器”。这里也看看。