以下是an example from 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';
}
我有两个问题:
std::vector<char> v( (std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>() );
,我不太明白它在做什么......为什么我们只能使用cout<<&v[0]
打印字符串“Hello,world”非常感谢!
答案 0 :(得分:14)
有人可以详细说明代码......
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>
,以便能够使用const char*
operator <<(...)
重载来打印向量}}
答案 1 :(得分:5)
默认构造的istreambuf_iterator
基本上是一个文件结束迭代器 - 也就是说,只有当它到达文件末尾时,另一个迭代器才会比较它。
因此,代码:
std::vector<char> v( (std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>() );
...从char
读取in
,直到第一个迭代器增加到等于第二个迭代器,这发生在第一个迭代器到达文件末尾时(并且仅当) stringstream,在这种情况下)。简而言之,它将文件的全部内容复制到矢量中。
印刷&#34;你好世界&#34; part有点简单:ostream对operator<<
有一个char *
重载,假设char *
指向一个C风格的字符串,所以它应该打印出整个字符串&#39} ; s指着。由于他们已经完成了push_back
向字符串添加'\0'
,因此它会成为C风格的字符串。
第二部分展示了即使你有两个迭代器进入流,你仍然只有一个流,并在该流中有一个读取位置。同时,每个迭代器都保存从流中读取的最新项的副本。
因此,无论何时将 迭代器(或任何迭代器)递增到同一个流中,它都会递增当前读取位置。因此,您从i1
和i2
开始,两者都指向流的开头。然后你增加i1
。这会增加阅读位置,并将b
读入i1
,因此当您取消引用i1
时,就会获得您所获得的内容。当您递增i2
时,会再次移动阅读位置,并将c
读取到i2
,因此取消引用i2
会给c
。
简而言之,使用两个(或更多)迭代器并不会改变流的性质 - 每次将任何迭代器增加到同一个流中时,它会读取<来自该流的em> next item - 以及&#34; next item&#34;始终由流本身根据其一个读取位置确定。