【问题标题】:streambuf, ostream, ostreambuf, istream, istreambuf and associated iteratorsstreambuf、ostream、ostreambuf、istream、istreambuf 和相关的迭代器
【发布时间】:2012-08-07 04:28:09
【问题描述】:

我想有人不得不问这些问题,所以请多多包涵。

让我们考虑以下野兽:

  • ostream
  • istream
  • iostream
  • 流缓冲
  • string - 按照本杰明的观察,这个不属于这里。
  • 字符串缓冲区

以及以下迭代器:

  • ostream_iterator
  • ostreambuf_iterator
  • istream_iterator
  • istreambuf_iterator

问题:

为什么没有iostream_iteratorstreambuf_iteratorstring_iterator(std::string::iterator 和 std::string::const_iterator 确实存在)或stringbuf_iterator ?

为什么上面列出的 4 个迭代器没有像 std::vector<T>::const_iterator 这样的 const 版本?

如果这些野兽不提供 begin() 和 end() 方法,我们应该如何迭代它们?以上4个迭代器的目的是什么?

N00b 问题:我在哪里可以找到详细说明这些类背后的逻辑以及如何使用它们的一些不错的示例的好参考?

希望有经验的人能为上述问题提供一个很好的答案。


PS:现实生活中的情况:

void writeToStream(std::ostream &out);
int main ()
{
    std::ostringstream byteStream;
    writeToStream(byteStream);
    std::string byteString = byteStream.str();

    for (unsigned short i = 0; i < byteString.size(); ++i)
    {
        //do something with each byteString[i]
    }
    return 0;
}

我的猜测是,我可以使用 ostream 并通过使用类似于 std::vector 的迭代器来迭代其元素,而不是使用 ostringstreamstr() 方法将其转换为 string ,但我找不到任何有关此的信息。

【问题讨论】:

  • 请记住,流是流,而不是容器(这意味着在大多数情况下,您无法返回和/或会破坏您读取的数据)
  • @PasmaHH:好的,这是一个很好的观点。谢谢! :) 不过,我仍然希望对这些问题进行详细解释。
  • 你为什么把string分组在里面?有string::iteratorstring::const_iteratorstring::begin()string::end()
  • @BenjaminLindley Oups...我的错。你是对的。

标签: c++ stl stream iterator buffer


【解决方案1】:

为什么没有 iostream_iterator、streambuf_iterator 或 stringbuf_iterator?

我不知道。虽然我猜这只是因为它们会更复杂,而且对它们的需求不够。

为什么上面列出的 4 个迭代器没有像 std::vector&lt;T&gt;::const_iterator?

一个 const 输入迭代器将是相当多余的,无论如何你只能从它们中读取,而不能写入它们。一个 const 输出迭代器将毫无意义,因为这会破坏它的唯一目的,即输出。

如果它们不这样做,我们应该如何迭代这些野兽中的任何一个 提供 begin() 和 end() 方法?的目的是什么 以上4个迭代器?

通过使用各自的构造函数创建迭代器,例如

std::istream_iterator<int> in_begin(std::cin), in_end;
std::ostream_iterator<int> out_begin(std::cout, "\n");
std::copy(in_begin, in_end, out_begin);

请注意,istream_iterator 的结束迭代器是通过简单地不向其构造函数传递任何参数来创建的,并且对于输出迭代器没有等效于 end()

【讨论】:

  • 迭代器是输入/输出限定的,因为您将它们用作源或目标,而不是两者,因为假设它们消耗或生成您不能返回的流以前的位置。
  • 感谢本杰明std::copy 的用法示例。您的 cmets 非常有用,但我决定接受 Loki 的回答,因为它包含更多细节。
【解决方案2】:

为什么没有:
* iostream_iterator
* streambuf_iterator

不知道。可能是因为在进行输入和输出时语义很难定义。当您在带有迭代器的流中前进然后后退时,您期望会发生什么?

  • string_iterator
  • stringbuf_iterator?

这些很容易被现有的迭代器覆盖:

std::string                  line; // load line.
std::stringstream            linestream(line);
std::istream_iterator<int>   lineIterator(linestream);

为什么上面列出的 4 个迭代器没有像 std::vector::const_iterator 这样的 const 版本?

因为当您遍历流时,流的状态正在发生变化。

如果这些野兽不提供 begin() 和 end() 方法,我们应该如何迭代它们?以上4个迭代器的目的是什么?

因为流通常是一个方向。您不是从头开始迭代,而是从流中的当前位置迭代到结尾。因此,您只需声明一个指定流的迭代器。迭代器从当前位置开始,向末尾移动。您可以通过不指定流来声明流迭代器的结束。

 std::istream_iterator<int>   loop(std::cin);
 for(;loop != std::istream_iterator<int>(); ++loop)
 {
     std::cout << *loop;
 }

N00b 问题:我在哪里可以找到详细说明这些类背后的逻辑以及如何使用它们的一些不错的示例的好参考?

这里是个好地方。
搜索“C++ istream_iterator”你会得到很多点击。

希望有经验的人能为上述问题提供一个很好的答案。

希望。

【讨论】:

  • 嗯,谢谢你的好答案和花时间提供它。在您的示例代码中,为什么将loopstd::istream_iterator&lt;int&gt;() 进行比较?
  • 因为:std::istream_iterator&lt;int&gt;() 是一个迭代器,它在容器上标记相当于 end() 的流的结束。当您将循环递增到流的末尾时,它将与这样创建的对象进行比较。
  • 好的,有道理。再次感谢!
【解决方案3】:

这些流迭代器的存在是为了使用标准算法直接从/向容器写入/读取流。所以不要写

for (vector<int>::iterator i=v.begin(); i!=v.end(); ++i)
    cout << *i <<"\n";

你可以只使用 std::copy:

copy(v.begin(), v.end(), ostream_iterator(cout, "\n"));

如需参考,请查看thisTC++PL 之类的内容。恕我直言,它们是一个巧妙的技巧,但并没有太大帮助,因为您几乎无法控制输入/输出。

【讨论】:

  • 什么是 TC++PL? “汤普金斯县公共图书馆”?
  • 抱歉,忘记链接了。这是 Stroustrup 的书。
  • 好的。谢谢!并为漂亮的 Apache 文档 +1。
猜你喜欢
  • 1970-01-01
  • 2011-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多