繁体   English   中英

对“std::istreambuf_iterator”的使用感到困惑

[英]Confused about usage of 'std::istreambuf_iterator'

以下是 来自 cppreference.com 的示例

The Code is:
#include <vector>
#include <sstream>
#include <iostream>
#include <iterator>

int main()
{
// typical use case: an input stream represented as a pair of iterators
std::istringstream in("Hello, world");
std::vector<char> v( (std::istreambuf_iterator<char>(in)),
                      std::istreambuf_iterator<char>() );
std::cout << "v has " << v.size() << " bytes. ";
v.push_back('\0');
std::cout << "it holds \"" << &v[0] << "\"\n";


// demonstration of the single-pass nature
std::istringstream s("abc");
std::istreambuf_iterator<char> i1(s), i2(s);
std::cout << "i1 returns " << *i1 << '\n'
          << "i2 returns " << *i2 << '\n';
++i1;
std::cout << "after incrementing i1, but not i2\n"
          << "i1 returns " << *i1 << '\n'
          << "i2 returns " << *i2 << '\n';
++i2; // this makes the apparent value of *i2 to jump from 'a' to 'c'
std::cout << "after incrementing i2, but not i1\n"
          << "i1 returns " << *i1 << '\n'
          << "i2 returns " << *i2 << '\n';

}

我有两个问题:

  1. 有人可以详细说明代码std::vector<char> v( (std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>() ); ,我不太明白它在做什么......以及为什么我们可以仅使用cout<<&v[0]来打印字符串“Hello, world”
  2. 为什么 *i2 的 apprent 值从“a”跳到“c”? 有人可以解释它的机制吗?

非常感谢!

有人能详细说明一下代码吗...

std::vector<T>有一个构造函数,它在<T>上有两个迭代器——一个用于范围的开头,一个用于范围的结尾。

该构造使得从输入流的输入流迭代器in

std::istreambuf_iterator<char>(in)

您可以继续访问其元素,直到到达流的末尾。 一旦到达流的末尾,迭代器就等同于使用默认构造函数创建的迭代器:

std::istreambuf_iterator<char>()

因此,传递这对迭代器会根据从输入流读取的数据构造一个vector<T> 整个流将被消耗。

为什么*i2的 apprent 值从"a"跳到"c"

两个迭代器都从同一个流中读取。 当您增加第一个迭代器时,它会从底层流中消耗'b' 同时, i2指的是流的第一个字符,它在构建时没有前进。

一旦你增加i2 ,它就会向流询问下一个字符。 字符'b'已被消耗,所以下一个字符是'c'

最后,该代码引入了一个您可能忽略的小技巧:它将一个空终止符推入vector<char>中,以便能够使用operator <<(...)const char*重载来打印向量。

默认构造的istreambuf_iterator基本上是一个文件结束迭代器——也就是说,只有当另一个迭代器到达文件末尾时,它才会与它比较。

因此,代码:

std::vector<char> v( (std::istreambuf_iterator<char>(in)),
                      std::istreambuf_iterator<char>() );

...从in读取char s in直到第一个迭代器增加到等于第二个迭代器,这发生在(并且仅当)第一个迭代器到达文件末尾(在本例中为 stringstream)。 简而言之,它将文件的全部内容复制到向量中。

打印“hello world”部分要简单一些:ostream 有一个operator<< char *重载,它假设char *指向一个 C 风格的字符串,所以它应该打印出指向的整个字符串。 由于他们已经执行push_back向字符串添加'\\0' ,这使其成为 C 样式字符串。

第二部分演示了即使您有两个迭代器进入流,您仍然只有一个流,并且在该流中只有一个读取位置。 同时,每个迭代器都持有它从流中读取的最新项目的副本。

因此,无论何时您增加任一迭代器(或任何迭代器到同一流中),它都会增加当前读取位置。 因此,您从i1i2开始,它们都指向流的开头。 然后你增加i1 这会增加读取位置,并将b读入i1 ,因此当您取消引用i1 ,这就是您将得到的。 当您增加i2 ,再次移动读取位置,并将c读入i2 ,因此取消引用i2将给出c

使用两个(或更多)迭代器不会改变流的性质——每次你将任何迭代器增加到同一个流中,从该流中读取下一个项目——并且“下一个项目”总是被确定由流本身,基于其一个读取位置。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM