21

通常的 STL 结构是:

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

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

谁能解释这段代码是如何工作的?

我的问题是我不太了解这部分:

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

2 回答 2

27

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

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

表达方式

  istream_iterator<string>(cin)  

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

cin >> string  

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

表达方式

istream_iterator<string>()  

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

最后一个:

back_inserter(col))

根据 back_inserter 文档:

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

它将所有读取的字符串添加到col.

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

于 2013-05-24T03:23:08.220 回答