有人可以详细说明代码......
std::vector<T>
有一个构造函数,它接受两个迭代器<T>
- 一个用于开头,一个用于范围的末尾.
此构造函数从输入流生成输入流迭代器in
:
std::istreambuf_iterator<char>(in)
您可以访问其元素,直到到达流的末尾.一旦到达流的末尾,迭代器就等同于使用默认构造函数创建的迭代器:
std::istreambuf_iterator<char>()
因此,传递这对迭代器会vector<T>
从输入流中读取的数据构造一个.整个流将被消耗.
为什么的apprent值
*i2
跳跃"a"
到"c"
?
两个迭代器都从同一个流中读取.当您递增第一个迭代器时,它将'b'
从基础流中消耗.在此期间,i2
指的是流的第一个字符,它在构建时没有前进.
递增后i2
,它会向流请求下一个字符.角色'b'
已被消耗,所以下一个角色是'c'
.
最后,代码提取了一个你可能忽略的小技巧:它将空终止符推入其中vector<char>
,以便能够使用const char*
重载来打印向量operator <<(...)
.
默认构造istreambuf_iterator
的基本上是文件结尾的迭代器,也就是说,另一个迭代器仅在到达文件末尾时才进行比较。
因此,代码:
std::vector<char> v( (std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>() );
...从char
s开始读取,in
直到第一个迭代器增加到等于第二个迭代器为止,这在(且仅当)第一个迭代器到达文件末尾(在这种情况下为stringstream)时发生。简而言之,它将文件的全部内容复制到向量中。
打印“ hello world”部分要简单一些:ostream有一个operator<<
for 的重载char *
,它假定char *
点在C样式的字符串上,因此它应该打印出所指向的整个字符串。由于他们已经完成了push_back
将a添加'\0'
到字符串的操作,因此使其成为C样式的字符串。
第二部分说明即使流中有两个迭代器,您仍然只有一个流,并且在该流中有一个读取位置。同时,每个迭代器都保存它从流中读取的最新项目的副本。
因此,每当您增加一个迭代器(或将任何迭代器添加到同一流中)时,它都会增加当前的读取位置。所以,你开始i1
和i2
两个指向流的开始。然后增加i1
。这将增加读取位置,并读取b
到中i1
,因此在取消引用时i1
,将得到此结果。当您增加时i2
,它将再次移动读取位置并读c
入i2
,因此i2
将取消引用c
。
简而言之,使用两个(或多个)迭代器不会改变流的性质(每次将任何迭代器递增到同一流中时,都会从该流中读取下一个项目)以及“下一个项目”始终由流本身根据其一个读取位置确定。