[英]Confused about usage of 'std::istreambuf_iterator'
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';
}
我有两个问题:
std::vector<char> v( (std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>() );
,我不太明白它在做什么......以及为什么我们可以仅使用cout<<&v[0]
来打印字符串“Hello, world”非常感谢!
有人能详细说明一下代码吗...
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 样式字符串。
第二部分演示了即使您有两个迭代器进入流,您仍然只有一个流,并且在该流中只有一个读取位置。 同时,每个迭代器都持有它从流中读取的最新项目的副本。
因此,无论何时您增加任一迭代器(或任何迭代器到同一流中),它都会增加当前读取位置。 因此,您从i1
和i2
开始,它们都指向流的开头。 然后你增加i1
。 这会增加读取位置,并将b
读入i1
,因此当您取消引用i1
,这就是您将得到的。 当您增加i2
,再次移动读取位置,并将c
读入i2
,因此取消引用i2
将给出c
。
使用两个(或更多)迭代器不会改变流的性质——每次你将任何迭代器增加到同一个流中,从该流中读取下一个项目——并且“下一个项目”总是被确定由流本身,基于其一个读取位置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.