繁体   English   中英

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

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

通常的STL结构是:

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

我们使用istream_iterator从std输入( cin )复制到向量。

谁能解释一下这段代码的工作原理

我的问题是我真的不明白这一部分:

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

首先,请注意,在这种情况下,根本不需要使用std::copy 您可以直接从迭代器初始化向量:

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

这可能不会使代码更容易理解。

至于代码如何工作,它可能比你想象的更直接。 一个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(); }
};

显然,我正在跳过更多,但这是我们关心的大部分内容。 因此,当您创建迭代器时,它会将流中的项读取(或尝试)到我称为data的变量中。 取消引用迭代器时,它会返回data 当您递增迭代器时,它会读取(或尝试)文件中的下一个项目。 尽管编写好像将一个迭代器与另一个迭代器进行比较,但operator==operator!=实际上只是检查文件的结尾1

然后由std::copy ,(再次简化)看起来像这样模糊:

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

因此,这将从输入迭代器读取和输入项,将该项写入输出迭代器,并重复直到当前位置的迭代器与输入结束的迭代器相比(当到达结束时将发生这种情况)文件)。 请注意,与其他迭代器不同,您允许与istream迭代器一起使用的唯一“结束”位置是文件的末尾。


  1. 请注意,从技术上讲,这不符合行为。 我简化了比较以保持简单。 两个默认构造的迭代器应该比较相等,如果从同一个流构造两个迭代器,它们应该至少在从流中读取任何内容之前进行比较。 这虽然没有什么实际区别 - 你在实际使用中看到的唯一比较是确定你是否已经到达文件的末尾。

以下部分答案引自C ++标准库:Nicolai M. Josuttis的教程和参考文章,稍作调整。

表达方式

  istream_iterator<string>(cin) 

创建一个从标准输入流cin读取的字符串迭代器。 模板参数string指定流迭代器读取此类型的元素。 使用通常的输入运算符>>读取这些元素。 因此,每次算法想要处理下一个元素时,istream迭代器将该期望转换为调用

 cin >> string 

字符串的输入运算符通常读取由空格分隔的一个单词。

表达方式

 istream_iterator<string>() 

调用istream迭代器的默认构造函数,它创建一个所谓的end-of-stream迭代器。 它表示您无法再读取的流。 字符串结束迭代器用作end of the rangeend of the range ,因此算法copycin读取所有字符串,直到它不再能够读取为止。

最后一个:

back_inserter(col))

根据back_inserter文档:

一个std :: back_insert_iterator,可用于将元素添加到容器c的末尾

它会将所有读入的字符串添加到col

有关详细信息,请参阅有关std :: istream_iteratorstd :: back_inserter的信息。

暂无
暂无

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

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