以下面两行代码为例:

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
}

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


当前回答

分离关注点

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

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

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

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

性能

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

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

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

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

其他回答

假设some_vector是用链表实现的。然后,在第i个位置请求一个项需要执行i个操作来遍历节点列表。现在,如果您使用迭代器,一般来说,它将尽最大努力尽可能高效(在链表的情况下,它将维护一个指向当前节点的指针,并在每次迭代中推进它,只需要一个操作)。

所以它提供了两件事:

使用的抽象:你只想迭代一些元素,你不关心如何去做 性能

除了所有其他优秀的答案之外……Int对向量来说可能不够大。相反,如果你想使用索引,使用size_type为你的容器:

for (std::vector<Foo>::size_type i = 0; i < myvector.size(); ++i)
{
    Foo& this_foo = myvector[i];
    // Do stuff with this_foo
}

如果要在迭代vector时向其添加/删除项,则可能需要使用迭代器。

some_iterator = some_vector.begin(); 
while (some_iterator != some_vector.end())
{
    if (/* some condition */)
    {
        some_iterator = some_vector.erase(some_iterator);
        // some_iterator now positioned at the element after the deleted element
    }
    else
    {
        if (/* some other condition */)
        {
            some_iterator = some_vector.insert(some_iterator, some_new_value);
            // some_iterator now positioned at new element
        }
        ++some_iterator;
    }
}

如果使用索引,则必须在数组中上下移动项以处理插入和删除。

我应该指出你也可以打电话

Std::for_each(some_vector.begin(), some_vector.end(), &do_stuff);

迭代器的另一个好处是,它们更好地允许你表达(和执行)你的const-preference。这个例子确保你不会在循环中改变向量:


for(std::vector<Foo>::const_iterator pos=foos.begin(); pos != foos.end(); ++pos)
{
    // Foo & foo = *pos; // this won't compile
    const Foo & foo = *pos; // this will compile
}