代码之家  ›  专栏  ›  技术社区  ›  Konrad

迭代器。为什么要使用它们呢?[复制品]

  •  21
  • Konrad  · 技术社区  · 16 年前

    这个问题已经有了答案:

    在STL库中,一些容器有迭代器,通常认为它们是遍历这些容器的一种高级方法,而不是简单的for循环,例如。

    for ( int i=0; i < vecVector.size(); i++ )
    {
    
    ..
    
    }
    

    有人能告诉我为什么,在什么情况下我应该使用迭代器,在什么情况下,请告诉我上面的代码片段?

    6 回复  |  直到 13 年前
        1
  •  27
  •   paercebal    13 年前

    注意,通常向量的实现不会使用“int”作为索引/大小的类型。所以您的代码至少会引起编译器警告。

    泛型

    迭代器增加了代码的通用性。

    例如:

    typedef std::vector<int> Container ;
    
    void doSomething(Container & p_aC)
    {
        for(Container::iterator it = p_aC.begin(), itEnd = p_aC.end(); it != itEnd; ++it)
        {
           int & i = *it ; // i is now a reference to the value iterated
           // do something with "i"
        }
    }
    

    现在,假设您将向量更改为一个列表(因为在您的例子中,列表现在更好了)。您只需要更改typedef声明,然后重新编译代码。

    如果您使用了基于索引的代码,那么就需要重新编写它。

    通路

    迭代器应该被看作是一种超级指针。 它“指向”值(如果是映射,则指向键/值对)。

    但它有方法移动到容器中的下一个项。或上一个。有些容器甚至提供随机访问(向量和deque)。

    算法

    大多数STL算法都适用于迭代器或迭代器的范围(同样,由于泛型)。这里,您将无法使用索引。

        2
  •  17
  •   Adam Bellaire    16 年前

    使用迭代器可以使代码对容器的实现不可知。如果容器的随机访问很便宜,那么性能方面就没有太大的差异。

    但在很多情况下,你不知道情况是否如此。如果您尝试在链接列表上使用您的方法,例如,通过订阅,容器将不得不在每次迭代中遍历列表以找到您的元素。

    因此,除非您确定对容器的随机访问是便宜的,否则请使用迭代器。

        3
  •  2
  •   Jamie Eisenhart    16 年前

    如果使用迭代器作为函数的参数,则可以将其与所使用的“容器”类型分离。例如,您可以将函数的结果定向到控制台输出,而不是向量(下面的示例)。这个技巧对于减少类之间的耦合非常强大。松耦合类更容易测试。

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    template <typename InputIterator, typename OutputIterator>
    void AddOne(InputIterator begin, InputIterator end, OutputIterator dest)
    {
        while (begin != end)
        {
            *dest = *begin + 1;
            ++dest;
            ++begin;
        }
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        vector<int> data;
        data.push_back(1);
        data.push_back(2);
        data.push_back(3);
    
        // Compute intermediate results vector and dump to console
        vector<int> results;
        AddOne(data.begin(), data.end(), back_inserter(results));
        copy(results.begin(), results.end(), ostream_iterator<int>(cout, " "));
        cout << endl;
    
        // Compute results and send directly to console, no intermediate vector required
        AddOne(data.begin(), data.end(), ostream_iterator<int>(cout, " "));
        cout << endl;
    
        return 0;
    }
    
        4
  •  1
  •   Ben Hoffstein    16 年前

    在您的示例中,对vecVector.size()的调用比使用迭代器效率低。迭代器本质上封装了您不必担心被迭代的容器的大小。此外,迭代器不必按顺序进行。它只需要以它认为合适的方式对下一个呼叫做出响应。

        5
  •  1
  •   Dave Van den Eynde    16 年前

    首先,如果你把向量转化成一个列表,上面的内容就不再有效了。

    迭代器允许您创建不需要知道所处理容器类型的函数模板。您甚至可以执行以下操作:

    #include <algorithm>
    
    void printvalue(double s)
    {
        // Do something with s
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        double s[20] = {0};
    
        std::for_each(s, s+20, printvalue);
    
        return 0;
    }
    

    这是因为标准指针也是有效的迭代器。

    戴夫

        6
  •  1
  •   Johann Gerell    16 年前

    迭代器主要是更高级别的抽象。

    您的代码段假定容器可以被索引。这是真的 std::vector<> 以及一些其他容器,例如原始数组。

    但是 std::set<> 完全缺乏索引和 std::map<> 将向其提供的任何参数插入映射-而不是您的 for -循环。

    此外,只有在经过测量和证明后,性能问题才是问题。