【问题标题】:Obtain an index into a vector using Iterators使用迭代器获取向量的索引
【发布时间】:2010-09-13 00:54:15
【问题描述】:

当迭代向量的元素时,最好使用迭代器而不是索引(参见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. 恢复到索引循环
    标准::向量向量;
    尺寸_t我;
    对于 ( i = 0; i 
    
  2. 计算偏移量
    标准::向量向量;
    std::vector::iterator it;
    对于 (它 = vec.begin(); 它!= vec.end(); ++it)
    {
       size_t i = 它 - vec.begin();
       // 使用我
    }
    
  3. 使用 std::distance
    标准::向量向量;
    std::vector::iterator it;
    对于 (它 = vec.begin(); 它!= vec.end(); ++it)
    {
       size_t i = std::distance(vec.begin(), it);
       // 使用我
    }
    

【问题讨论】:

    标签: c++ indexing vector iterator


    【解决方案1】:

    如果您打算只使用向量,则可能需要切换回索引循环,因为它比迭代器循环更清楚地传达了您的意图。但是,如果您的程序在未来的发展可能导致容器的变化,您应该坚持使用迭代器并使用 std::distance,它保证可以与所有标准迭代器一起使用。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        std::distance(vec.begin(), it) 会给你it 指向的索引,假设它指向vec

        卡尔

        【讨论】:

          【解决方案4】:

          恢复到索引循环。

          基本上在 90% 的情况下,迭代器是优越的,这是 10% 的情况之一。使用迭代器会使代码更复杂,因此更难理解,而使用迭代器的全部原因首先是为了简化代码。

          【讨论】:

          • 忘了提及性能,通常可以安全地假设索引循环会具有更好的性能,但两种情况下的性能会非常相似。
          • 我不能说我同意。循环体可能包含其他取消引用迭代器的代码。迭代器并不是为了让你的代码更简单,它们让你的代码更通用。通过使用迭代器,您可以将向量交换为列表,它仍然可以工作。
          • 另外,std::map 或 std::set 迭代器远非愚蠢。如果我遍历所有可能的键,它可能需要很长时间。另外,我必须对每个键进行 O(log(n)) 查找。所以我的循环需要 O(m*log(n))。使用迭代器,我可以在 O(n) 时间内遍历集合。
          【解决方案5】:

          您缺少一个解决方案:保留索引以备不时之需,但不要将其用作循环条件。也适用于列表,成本(每个循环)是 O(n) 和一个额外的寄存器。

          【讨论】:

            【解决方案6】:

            出于未来发展的原因,我总是倾向于使用迭代器。

            在上面的示例中,如果您可能决定将 std::vector 替换为 std::set(也许您需要一个唯一的元素集合),使用迭代器和 distance() 将继续有效。

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

            【讨论】:

              【解决方案7】:

              对于向量,我总是使用整数方法。向量中的每个索引与数组查找的速度相同。如果我要大量使用该值,我会创建一个对它的引用,为方便起见。

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

              我将迭代器用于其他容器类型,有时当您不需要循环变量时。但是,如果您需要循环变量,除了使循环更难键入之外,您什么也不做。 (我等不及 c++0x 的自动......)

              【讨论】:

                猜你喜欢
                • 2014-09-19
                • 2010-10-14
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-02-08
                • 2014-12-26
                • 2016-08-25
                相关资源
                最近更新 更多