2008-09-25 90 views
5

迭代遍历向量的元素时,最好使用迭代器而不是索引(请参阅Why use iterators instead of array indices?)。使用迭代器获取向量的索引

std::vector<T> vec; 
std::vector<T>::iterator it; 
for (it = vec.begin(); it != vec.end(); ++it) 
{ 
    // do work 
} 

然而,可能有必要使用索引在循环体。在这种情况下,考虑性能和灵活性/可扩展性,以下哪项更可取?

  1. 恢复到索引循环
     
    std::vector vec; 
    size_t i; 
    for (i = 0; i < vec.size(); ++i) 
    { 
        // use i 
    } 
    
  2. 计算偏移
     
    std::vector vec; 
    std::vector::iterator it; 
    for (it = vec.begin(); it != vec.end(); ++it) 
    { 
        size_t i = it - vec.begin(); 
        // use i 
    } 
    
  3. 使用std ::距离
     
    std::vector vec; 
    std::vector::iterator it; 
    for (it = vec.begin(); it != vec.end(); ++it) 
    { 
        size_t i = std::distance(vec.begin(), it); 
        // use i 
    } 
    

回答

13

如果您打算专门使用矢量,您可能需要切换回索引循环,因为它比迭代器循环更清楚地表达您的意图。但是,如果将来的程序演化可能会导致容器发生变化,则应该坚持使用迭代器并使用std :: distance,这可以保证与所有标准迭代器一起工作。

8

使用std ::距离是有点更通用的,因为它适用于所有的迭代器,不只是随机访问迭代器。在随机访问迭代器的情况下,它应该和它一样快--vec.begin()。

它 - vec.begin()基本上是指针算术。

4

还原为索引循环。

基本上在90%的情况下,迭代器是优越的,这是其中的10%。通过使用迭代器,使得代码更复杂,因此难以理解,因为首先使用迭代器的所有原因都是为了简化代码。

+0

忘了提到性能,通常假设索引循环会有更好的性能是安全的,但在这两种情况下性能会非常相似。 – Guvante 2008-09-25 09:39:32

1

您错过了一个解决方案:在需要的情况下保留索引,但不要将其用作循环条件。也在列表上工作,成本(每个循环)是O(n)和一个额外的寄存器。

0

我总是倾向于保持迭代器的未来发展的原因。

在上面的例子中,如果你可能决定换出std :: set作为std :: set(也许你需要一个唯一的元素集合),使用迭代器和distance()将继续工作。

我很确定任何性能问题都会被优化到可以忽略的程度。

0

对于向量,我总是使用整数方法。向量中的每个索引与数组查找的速度相同。如果我打算使用这个值,为了方便起见,我创建了一个参考。

矢量迭代器在理论上可能比索引稍快,因为它们使用指针运算来遍历列表。但是,通常我会发现可读性值得最小的运行时间差异。

我使用其他容器类型的迭代器,有时候当你不需要循环变量时。但是,如果你需要循环变量,除了让你的循环更难以输入外,你什么都不做。 (我不能等待C++ 0x的自动..)