以下面两行代码为例:

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
}

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


当前回答

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

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

其他回答

迭代器的另一个好处是,它们更好地允许你表达(和执行)你的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
}

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

所以它提供了两件事:

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

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

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;
    }

}

如果你可以访问c++ 11的特性,那么你也可以使用一个基于范围的for循环来迭代你的vector(或任何其他容器),如下所示:

for (auto &item : some_vector)
{
     //do stuff
}

这个循环的好处是,您可以直接通过item变量访问vector的元素,而不会有搞乱索引或在解引用迭代器时出错的风险。此外,占位符auto可以防止您重复容器元素的类型, 这使您更接近于容器无关的解决方案。

注:

如果您需要循环中的元素索引,并且容器中存在操作符[](并且对您来说足够快),那么最好采用第一种方法。 基于范围的for循环不能用于在容器中添加/删除元素。如果你想这样做,那么最好坚持布莱恩·马修斯给出的解决方案。 如果你不想改变容器中的元素,那么你应该如下所示使用关键字const: for (auto const &item: some_vector){…}。

我不使用迭代器的原因与我不喜欢foreach-statements的原因相同。当有多个内部循环时,如果不记住所有的局部值和迭代器名称,就很难跟踪全局/成员变量。我发现有用的是在不同的情况下使用两组指标:

for(int i=0;i<anims.size();i++)
  for(int j=0;j<bones.size();j++)
  {
     int animIndex = i;
     int boneIndex = j;


     // in relatively short code I use indices i and j
     ... animation_matrices[i][j] ...

     // in long and complicated code I use indices animIndex and boneIndex
     ... animation_matrices[animIndex][boneIndex] ...


  }

例如,我甚至不想将“animation_matrices[I]”缩写为一些随机的“anim_matrix”-name -iterator,因为这样你就不能清楚地看到这个值来自哪个数组。