通常的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>()
答案 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 :(得分: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
,因此算法copy
从cin
读取所有字符串,直到它不再再读取为止。
最后一个:
back_inserter(col))
根据back_inserter文档:
std :: back_insert_iterator,可用于将元素添加到容器的末尾c
它会将所有读入的字符串添加到col
。
您可以找到有关std::istream_iterator和std::back_inserter的详细信息。