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

时间:2013-05-24 03:10:34

标签: c++ stl stream iterator

通常的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>()

2 个答案:

答案 0 :(得分:22)

首先,请注意,在这种情况下,根本不需要使用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. 请注意,从技术上讲,这不符合行为。我简化了比较以保持简单。两个默认构造的迭代器应该比较相等,如果从同一个流构造两个迭代器,它们应该至少在从流中读取任何内容之前进行比较。这没有什么实际意义 - 你在实际使用中看到的唯一比较是确定你是否已经到达文件的末尾。

答案 1 :(得分:5)

下面的部分答案来自C ++标准库:Nicolai M. Josuttis的教程和参考文章,并进行了一些调整。

  

表达式

  istream_iterator<string>(cin)  
     

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

的调用。
cin >> string  
     

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

     

表达式

istream_iterator<string>()  
     

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

最后一个:

back_inserter(col))

根据back_inserter文档:

  

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

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

您可以找到有关std::istream_iteratorstd::back_inserter的详细信息。