[英]Confused about usage of 'std::istreambuf_iterator'
Following is an example from cppreference.com ,以下是 来自 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';
}
I have two questions:我有两个问题:
std::vector<char> v( (std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>() );
std::vector<char> v( (std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>() );
, I do not quite understand what it's doing..and why can we print the string "Hello, world" just by using cout<<&v[0]
cout<<&v[0]
来打印字符串“Hello, world” Thanks so much!非常感谢!
Can someone elaborate on the code ...
有人能详细说明一下代码吗...
std::vector<T>
has a constructor that takes two iterators on <T>
- one for the beginning and one for the end of the range. std::vector<T>
有一个构造函数,它在<T>
上有两个迭代器——一个用于范围的开头,一个用于范围的结尾。
This constructor makes an input stream iterator from an input stream in
:该构造使得从输入流的输入流迭代器
in
:
std::istreambuf_iterator<char>(in)
You can access its elements going forward until you reach the end of the stream.您可以继续访问其元素,直到到达流的末尾。 Once you reach the end of stream, the iterator becomes equivalent to an iterator created using the default constructor:
一旦到达流的末尾,迭代器就等同于使用默认构造函数创建的迭代器:
std::istreambuf_iterator<char>()
Therefore, passing this pair of iterators constructs a vector<T>
from the data read from an input stream.因此,传递这对迭代器会根据从输入流读取的数据构造一个
vector<T>
。 The entire stream will be consumed.整个流将被消耗。
Why does the apprent value of
*i2
jump for"a"
to"c"
?为什么
*i2
的 apprent 值从"a"
跳到"c"
?
Both iterators are reading from the same stream.两个迭代器都从同一个流中读取。 When you increment the first iterator, it consumes
'b'
from the underlying stream.当您增加第一个迭代器时,它会从底层流中消耗
'b'
。 In the meantime, i2
refers to the first character of the stream, which it got without advancing at the time when it has been constructed.同时,
i2
指的是流的第一个字符,它在构建时没有前进。
Once you increment i2
, it asks the stream for the next character.一旦你增加
i2
,它就会向流询问下一个字符。 Character 'b'
has been consumed already, so the next character is 'c'
.字符
'b'
已被消耗,所以下一个字符是'c'
。
Finally, the code pulls a little trick that you may have overlooked: it pushes a null terminator into the vector<char>
in order to be able to print the vector using the const char*
overload of operator <<(...)
.最后,该代码引入了一个您可能忽略的小技巧:它将一个空终止符推入
vector<char>
中,以便能够使用operator <<(...)
的const char*
重载来打印向量。
A default-constructed istreambuf_iterator
is basically an end-of-file iterator--that is, another iterator will compare equal to it only when it reaches the end of the file.默认构造的
istreambuf_iterator
基本上是一个文件结束迭代器——也就是说,只有当另一个迭代器到达文件末尾时,它才会与它比较。
Therefore, the code:因此,代码:
std::vector<char> v( (std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>() );
...reads char
s from in
until the first iterator has been incremented to equal the second iterator, which happens when (and only when) the first iterator reaches the end of the file (stringstream, in this case). ...从
in
读取char
s in
直到第一个迭代器增加到等于第二个迭代器,这发生在(并且仅当)第一个迭代器到达文件末尾(在本例中为 stringstream)。 In short, it copies the entire contents of the file into the vector.简而言之,它将文件的全部内容复制到向量中。
The printing "hello world" part is a bit simpler: ostream has an operator<<
overload for char *
, which assumes that the char *
points at a C-style string, so it should print out the entire string that's pointed at.打印“hello world”部分要简单一些:ostream 有一个
operator<<
char *
重载,它假设char *
指向一个 C 风格的字符串,所以它应该打印出指向的整个字符串。 Since they've done a push_back
to add a '\\0'
to the string, that makes it a C-style string.由于他们已经执行
push_back
向字符串添加'\\0'
,这使其成为 C 样式字符串。
The second part is demonstrating that even though you have two iterators into the stream, you still have only one stream, and one read position in that stream.第二部分演示了即使您有两个迭代器进入流,您仍然只有一个流,并且在该流中只有一个读取位置。 At the same time, each iterator holds a copy of the most recent item it read from the stream.
同时,每个迭代器都持有它从流中读取的最新项目的副本。
Therefore, anytime you increment either iterator (or any iterator into the same stream) it increments the current read position.因此,无论何时您增加任一迭代器(或任何迭代器到同一流中),它都会增加当前读取位置。 So, you start with
i1
and i2
both pointing to the beginning of the stream.因此,您从
i1
和i2
开始,它们都指向流的开头。 Then you increment i1
.然后你增加
i1
。 That increments the read position, and reads b
into i1
, so when you dereference i1
, that's what you'll get.这会增加读取位置,并将
b
读入i1
,因此当您取消引用i1
,这就是您将得到的。 When you increment i2
, that moves the read position again, and reads c
into i2
, so dereferencing i2
will give c
.当您增加
i2
,再次移动读取位置,并将c
读入i2
,因此取消引用i2
将给出c
。
The use of two (or more) iterators doesn't change the nature of the stream--every time you increment any iterator into the same stream, that reads the next item from that stream--and the "next item" is always determined by the stream itself, based on its one read position.使用两个(或更多)迭代器不会改变流的性质——每次你将任何迭代器增加到同一个流中,从该流中读取下一个项目——并且“下一个项目”总是被确定由流本身,基于其一个读取位置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.