【问题标题】:How do iostream iterators work?iostream 迭代器如何工作?
【发布时间】:2014-01-20 07:06:27
【问题描述】:

从标准模板库中,我了解到istreamostream 迭代器。我无法理解它们是如何工作的。

我也不明白为什么要使用它们。它们为什么有用?

【问题讨论】:

  • +1 不是为了这个问题,而是为了想出插入和流迭代器想法的天才。这真是令人难以置信的聪明。

标签: c++ c++11 iterator iostream


【解决方案1】:

流迭代器为 iostream 的格式化提取/插入操作提供迭代器接口。例如,考虑以下情况:

std::vector<int> v;

for (int n; std::cin >> n; )
    v.push_back(n);

这相当于:

std::vector<int> v(std::istream_iterator<int>(std::cin), 
                   std::istream_iterator<int>{});

推进迭代器执行一次提取,类似于std::cin &gt;&gt; n;如果提取失败,则迭代器采用奇异状态,这也是默认构造的迭代器的状态。

就其本质而言,这些流迭代器是单通,即最弱的一种迭代器:您只能访问“范围”中的每个元素一次,并且永远不会返回;并且从同一流构建的两个非结束迭代器比较相等,尽管这对于取消引用的值没有任何意义。 (但请注意,如果您不取消引用迭代器,是否会尝试第一次提取,这是一个奇怪的缺乏特异性。)

为了完整起见,输出流迭代器可以类似地用于将流转换为“容器”,这对于使用迭代器的算法很有用:

std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, "\n"));

输出流迭代器在分配时执行它们的工作;其他操作都是空操作。


有趣的是,没有包装getline 的流迭代器;人们经常自己编写一个,因为迭代器接口在很多方面都很有用。

【讨论】:

    【解决方案2】:

    流迭代器允许您将流用作源或目标,例如期望使用输入或输出迭代器的算法。

    它们主要用于为基本功能提供统一接口,因此您不需要(例如)在内存中的某个集合中创建中间结果,然后将数据从那里复制到输出文件(输入也是如此)。

    就其工作方式而言,istream_iterator 通常在内部存储一个 T 对象。当您创建迭代器时,它会从带有stream &gt;&gt; value; 的文件中读取(或尝试)一个 T。 operator * 使您可以访问该值。 operator++ 读取下一个值。

    同样,ostream_iterator 会在您分配项目时将项目写入文件。由于流自动前进,operator++ 通常不会做任何事情(除了返回对迭代器的引用)。如果你真的想深入研究细节(比如它们),你可以看看我前段时间发的infix_ostream_iterator

    【讨论】:

      【解决方案3】:

      实际上,流迭代器本身并没有用。在迭代器上运行一组算法会使它们变得有用。

      【讨论】:

      • 难道不是算法本身没有用,而是只有在你有一组迭代器可以工作时它们才变得有用?
      • 这是一种先有鸡还是先有蛋的情况。
      • @KerrekSB 或者那样,当然(但算法使用迭代器的概念)
      • @ZacHowland 幸运的是,在算法到来之前,鸡蛋已经从鸡中孵出来了:指针很容易与算法一起使用,而且即使没有算法,它们也很有用。
      • @DietmarKühl 是的,也不是。对于不涉及某些处理(又名算法)的指针,您会做什么有用的操作? ;)
      【解决方案4】:

      作为一个例子来说明 Kerrek 和 Jerry 已经说过的话:

      而不是这样写:

      std::vector<int> vInts;
      int n;
      while (fin >> n) // where fin is an open ifstream
          vInts.push_back(n);
      // ...
      for (int i = 0; i < vInts.size(); ++i)
          cout << vInts[i] << endl;
      

      istream_iteratorostream_iterator 允许您在一行中编写执行相同操作的代码:

      copy(istream_iterator<int>(fin), istream_iterator<int>(), ostream_iterator<int>(cout, "\n"));
      

      这避免了临时存储和潜在的循环条件错误(例如,如果您要编写 &lt;= 而不是 &lt;)。

      由于标准算法使用迭代器,具有 istreams 和 ostreams 的迭代器允许使用具有许多常见算法的流。

      【讨论】:

        猜你喜欢
        • 2012-08-28
        • 2015-05-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-26
        • 2011-10-07
        • 2020-06-13
        • 1970-01-01
        相关资源
        最近更新 更多