Herb提出了一种循环向量的方法:
for(vector<int>::iterator i = v.begin(); i < v.end(); i++) {
cout << *i << endl;
}
他将此代码替换为:
copy(v.begin(), v.end(), ostream_iterator<int>(cout, "\n"));
我正在努力了解这是如何工作的,或者为什么会这样。我查找了复制功能,文档说它等同于:
template<class InputIterator, class OutputIterator>
OutputIterator copy (InputIterator first, InputIterator last,
OutputIterator result)
{
while (first!=last) {
*result = *first;
++result; ++first;
}
return result;
}
所以我提出了一个问题,“当我们* OutputIterator会发生什么?”
reference operator*() const;
Dereference iterator
Returns *this.
这就是我感到困惑的地方。我没有看到OutputIterator指向的定义。另外,我看不到行*result = *first;
可能如何转换为调用cout << *i;
答案 0 :(得分:5)
您只查找OutputIterator
的内容。 OutputIterator
只是标准库中的一堆类型满足的一组要求。其中一种类型是std::ostream_iterator
,因此您需要在std::copy
的上下文中查看其行为。
因此在复制算法中,我们正在进行*result = *first
。首先,operator*
的{{1}}什么都不做 - 它只返回迭代器本身。当我们分配给这个迭代器时,就会发生魔法。如果查找std::ostream_iterator::operator=
,您将看到分配给此迭代器将(使用std::ostream_iterator
)插入到构造它的流中。因此,您案例中的作业将流入<<
。
此后,std::cout
和result
都会增加。递增first
(result
)无效,递增std::ostream_iterator
将移动到向量中的下一个元素。然后在下一次迭代中,将下一个元素再次插入first
,依此类推。
正如您所看到的,std::cout
并不像您期望典型迭代器的行为那样(通过一系列元素移动,在这些元素上执行间接操作会为您提供当前元素)。但是,它 符合std::ostream_iterator
的要求,因此可以作为一个。
以下是来自libstdc ++的OutputIterator
的实现:
std::ostream_iterator::operator=
忽略第一行的断言,我们可以看到它然后将/// Writes @a value to underlying ostream using operator<<. If
/// constructed with delimiter string, writes delimiter to ostream.
ostream_iterator&
operator=(const _Tp& __value)
{
__glibcxx_requires_cond(_M_stream != 0,
_M_message(__gnu_debug::__msg_output_ostream)
._M_iterator(*this));
*_M_stream << __value;
if (_M_string) *_M_stream << _M_string;
return *this;
}
插入其内部__value
流中。然后,如果有一个分隔符集_M_stream
,它也会插入_M_string
。然后它返回。