简体   繁体   English

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

[英]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:我有两个问题:

  1. Can someone elaborate on the code 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”
  2. Why does the apprent value of *i2 jump for "a" to "c"?为什么 *i2 的 apprent 值从“a”跳到“c”? can someone explain the mechanisms of it?有人可以解释它的机制吗?

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.因此,您从i1i2开始,它们都指向流的开头。 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.

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