简体   繁体   English

std :: copy如何与流迭代器一起使用

[英]How does std::copy work with stream iterators

A usual STL construct is: 通常的STL结构是:

vector<string> col;
copy(istream_iterator<string>(cin), istream_iterator<string>(),
    back_inserter(col));

where we use an istream_iterator to copy from std input ( cin ) to a vector. 我们使用istream_iterator从std输入( cin )复制到向量。

Can anyone explain how this code works? 谁能解释一下这段代码的工作原理

my problem is that I don't really understand this part: 我的问题是我真的不明白这一部分:

istream_iterator<string>(cin), istream_iterator<string>()

First, note that in this case, there's no real need to use std::copy at all. 首先,请注意,在这种情况下,根本不需要使用std::copy You can just initialize the vector directly from the iterators: 您可以直接从迭代器初始化向量:

vector<string> col((istream_iterator<string>(cin)),
                    istream_iterator<string>());

This probably doesn't make the code a whole lot easier to understand though. 这可能不会使代码更容易理解。

As far as how the code works, it's probably a little more straighforward than you think. 至于代码如何工作,它可能比你想象的更直接。 An istream_iterator looks vaguely like this: 一个istream_iterator看起来像这样:

template <class T>
class istream_iterator { 
    std::istream *is;
    T data;
public:
    istream_iterator(std::istream &is) : is(&is) { ++(*this); }
    istream_iterator() : is(nullptr) {}

    T operator++() { (*is) >> data; return *this; }
    T operator++(int) { (*is) >> data; return *this; }

    T const &operator*() { return data; }   

    bool operator !=(istream_iterator &end) { return (*is).good(); }
    bool operator ==(istream_iterator &end) { return !(*is).good(); }
};

Obviously there's more more I'm skipping over, but that's most of what we care about here. 显然,我正在跳过更多,但这是我们关心的大部分内容。 So, what happens is that when you create the iterator, it reads (or attempts to) an item from the stream into the variable I've called data . 因此,当您创建迭代器时,它会将流中的项读取(或尝试)到我称为data的变量中。 When you dereference the iterator, it returns data . 取消引用迭代器时,它会返回data When you increment the iterator, it reads (or attempts to) the next item from the file. 当您递增迭代器时,它会读取(或尝试)文件中的下一个项目。 Despite being written as if they compare one iterator to another, operator== and operator!= really just check for the end of the file 1 . 尽管编写好像将一个迭代器与另一个迭代器进行比较,但operator==operator!=实际上只是检查文件的结尾1

That's then used by std::copy , which (again simplified) looks vaguely like this: 然后由std::copy ,(再次简化)看起来像这样模糊:

template <class InIt, class OutIt>
void std::copy(InIt b, InIt e, OutIt d) { 
    while (b != e) {
        *d = *b;
        ++b;
        ++d;
    }
}

So, this reads and item from the input iterator, writes that item to the output iterator, and repeats until the iterator for the current position compares equal to the iterator for the end of the input (which will happen when you reach the end of the file). 因此,这将从输入迭代器读取和输入项,将该项写入输出迭代器,并重复直到当前位置的迭代器与输入结束的迭代器相比(当到达结束时将发生这种情况)文件)。 Note that unlike other iterators, the only "end" position you're allowed to use with an istream iterator is the end of the file. 请注意,与其他迭代器不同,您允许与istream迭代器一起使用的唯一“结束”位置是文件的末尾。


  1. Note that technically, this isn't conforming behavior. 请注意,从技术上讲,这不符合行为。 I've simplified comparison to keep things simple. 我简化了比较以保持简单。 Two default-constructed iterators should compare equal, and if you construct two iterators from the same stream, they should compare equal at least before you've read anything from the stream. 两个默认构造的迭代器应该比较相等,如果从同一个流构造两个迭代器,它们应该至少在从流中读取任何内容之前进行比较。 This makes little practical difference though -- the only comparison you seen in real use is to determine whether you've reached the end of file yet. 这虽然没有什么实际区别 - 你在实际使用中看到的唯一比较是确定你是否已经到达文件的末尾。

Part of the answer below is quoted from C++ standard library: A tutorial and reference by Nicolai M. Josuttis with a little tweaks. 以下部分答案引自C ++标准库:Nicolai M. Josuttis的教程和参考文章,稍作调整。

The expression 表达方式

  istream_iterator<string>(cin) 

creates a string iterator that reads from the standard input stream cin . 创建一个从标准输入流cin读取的字符串迭代器。 The template argument string specifies that the stream iterator reads elements of this type. 模板参数string指定流迭代器读取此类型的元素。 These elements are read with the usual input operator >>. 使用通常的输入运算符>>读取这些元素。 Thus, each time the algorithm wants to process the next element, the istream iterator transforms that desire into a call of 因此,每次算法想要处理下一个元素时,istream迭代器将该期望转换为调用

 cin >> string 

The input operator for strings usually reads one word separated by whitespaces. 字符串的输入运算符通常读取由空格分隔的一个单词。

The expression 表达方式

 istream_iterator<string>() 

calls the default constructor of the istream iterators that creates a so-called end-of-stream iterator. 调用istream迭代器的默认构造函数,它创建一个所谓的end-of-stream迭代器。 It represents a stream from which you can no longer read. 它表示您无法再读取的流。 The end-of-string iterator is used as the end of the range , so the algorithm copy reads all strings from cin until it can no longer read any more. 字符串结束迭代器用作end of the rangeend of the range ,因此算法copycin读取所有字符串,直到它不再能够读取为止。

The last one: 最后一个:

back_inserter(col))

according to back_inserter documentation: 根据back_inserter文档:

A std::back_insert_iterator which can be used to add elements to the end of the container c 一个std :: back_insert_iterator,可用于将元素添加到容器c的末尾

It will add all read in strings into col . 它会将所有读入的字符串添加到col

You can find information about std::istream_iterator and std::back_inserter for details. 有关详细信息,请参阅有关std :: istream_iteratorstd :: back_inserter的信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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