【问题标题】:When to write an iterator?何时编写迭代器?
【发布时间】:2010-03-24 17:37:00
【问题描述】:

我知道这可能是一个愚蠢的问题。我什么时候需要编写自己的迭代器?只是在设计我自己的容器类时?还有其他时候我想创建自己的迭代器吗?

示例将被占用。

-乔恩

【问题讨论】:

  • 从答案的内容来看,你会认为那里的每个人都在狂热地编写迭代器!就个人而言,我想我可能在我的 C++ 职业生涯中这样做过两次。
  • 如答案所示,有时实现自定义迭代器是有意义的,但这种情况很少见。如果您的容器类是在 STL 容器之上构建的,那么只公开底层容器的迭代器而不是滚动您自己的迭代器可能是合适的。
  • 我认为人们通常会提到某些库中提供的迭代器。例如,查看boost.org/doc/libs/1_42_0/libs/iterator/doc/…。无需自己实现这些;)

标签: c++ stl iterator


【解决方案1】:

是的,还有其他时间。举几个例子:

  1. 一个 filter_iterator 只返回容器中项目的过滤子集。
  2. 仅返回对象的一部分的选择迭代器。
  3. 一个 ostream_iterator 将分隔符放在项目之前或之间,而不是在它们之后。

【讨论】:

    【解决方案2】:

    任何时候您需要迭代一系列数据,并且尚未定义适合您需求的迭代器。

    通常,您使用迭代器来遍历容器,但这远不是唯一的用途。

    迭代器还可以遍历数据库查询的结果,或从流中读取的输入(std::istream_iteratorstd::istreambuf_iterator 已经这样做了),或者您可能需要特殊的遍历顺序或策略。也许您想遍历“此向量的每个成员,其索引可被四整除”,或“此字符串中的每个大写字母”,或您能想到的任何其他内容。

    【讨论】:

    • +1:逃避其他答案的一些其他示例:boost::filesystem::directory_iterator 不会迭代容器,而是迭代目录。 pqxx::result::iterator 迭代从查询到数据库的结果,boost::asio::tcp::resolver::iterator 迭代 tcp 端点......它们都不是容器,但它们使用迭代器习语。
    • 匹配字符串/正则表达式搜索等
    【解决方案3】:

    当您有一个类(很可能是一个容器)并且您希望允许您的用户方便地遍历它而不暴露实现细节时,您需要创建一个迭代器。

    当您拥有一系列类(同样,最有可能是容器)并且您希望为您的用户提供所有这些类的统一迭代/遍历接口时更是如此,即使它们的实现非常不同(即链表与数组)。

    【讨论】:

      【解决方案4】:

      您需要为自己的容器类编写自己的迭代器,或者在迭代标准容器时需要非标准行为。

      【讨论】:

        【解决方案5】:

        实现迭代器非常有用,我经常这样做。迭代器是一个简单的概念,每个人都知道如何使用。迭代器让您可以使用 STL 算法。

        通常,您可以实现迭代器来简化常用操作系统 API 的使用,例如 Windows 的FindNextFile

        当你写一个file_iterator(已经存在于boost中),你可以突然做到:

        file_iterator itBegin; // initialize appropriately
        file_iterator itEnd;
        std::vector< HANDLE > vecFiles( itBegin, itEnd );
        

        获取所有匹配文件的句柄列表。如果没有迭代器,必要的 API 调用会使您的代码更难阅读。

        将迭代器视为简单的概念,让您可以写出您真正想说的内容并抽象出最重要的细节。如果您必须实现一个本身难以理解的复杂算法,您希望减少代码混乱。

        如果您有二维结构,例如std::vector,换句话说,一个表,其中每个内部向量都需要具有相同的长度,您可能需要遍历内部向量的每个第 n 个元素。如果这种情况发生得足够频繁,那么当您实现迭代器而不是在整个代码中传播嵌套的 for 循环时,您的代码可能会变得更加简单。

        【讨论】:

          【解决方案6】:

          我可以看到您想要创建新迭代器的两种情况:

          • 用于您自己的容器类(正如您自己指出的那样)。
          • 具有现有容器类的自定义行为的迭代器。 STL 例如有backwards iterators。也许您想要一个只返回每三个元素的every_3rd_iterator?这样的迭代器可能会被实现为围绕现有迭代器的适配器。

          【讨论】:

            【解决方案7】:

            除了过滤器和选择迭代器之外,我唯一一次用 C++ 编写迭代器是为了让 3rd 方容器类与 stl 算法配合得很好。例如

            • CORBA 序列的随机访问迭代器
            • CORBA 序列的后插入器
            • XML Dom 的双向迭代器,它将一个 dom 节点转换为一个迭代器,使我能够使用 foreach 并在兄弟节点上进行转换。

            总的来说,我不喜欢编写迭代器,因为它们很难,有很多事情需要处理。然而,使用 boost 迭代器库,这项任务变得更加容易。

            【讨论】:

            • 其实我昨天才下载boost。现在,如果我能构建单独的库就好了..
            • 嗨 Jon,我之前也一直在努力编译 boost 库。然而,只需要构建一些库。大多数是仅包含标头的库,不需要仅包含在内。迭代器库就是其中之一
            【解决方案8】:

            您可能还想使用它们来迭代数字序列,例如斐波那契数或素数。这些可以通过其他方式完成,可能更容易,但有时使用迭代器来处理这些事情是有意义的。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-02-20
              • 1970-01-01
              • 1970-01-01
              • 2013-05-01
              • 1970-01-01
              • 1970-01-01
              • 2018-09-17
              • 1970-01-01
              相关资源
              最近更新 更多