Herb 提出了一种遍历 vector 的方法:
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;
最佳答案
您只查找了一个 OutputIterator
做。 OutputIterator
只是标准库中的一堆类型满足的一组要求。其中一种类型是 std::ostream_iterator
,因此您需要查看其在 std::copy
上下文中的行为方式.
所以在复制算法中,我们正在做 *result = *first
.首先,operator*
对于 std::ostream_iterator
什么都不做 - 它只是返回迭代器本身。当我们分配给这个迭代器时,魔法就发生了。如果你查找 std::ostream_iterator::operator=
,你会看到分配给这个迭代器将插入(使用 <<
)到它构造的流中。因此,您案例中的作业将流入 std::cout
.
在此之后,result
和 first
递增。递增 result
( std::ostream_iterator
) 没有效果,递增 first
将移动到 vector 中的下一个元素。然后在下一次迭代中,下一个元素被插入到 std::cout
中。再次等等。
如您所见,std::ostream_iterator
并没有真正按照您期望的典型迭代器的行为方式行事(遍历一系列元素,在这些元素上执行间接操作会为您提供当前元素)。但是,它确实满足 OutputIterator
的要求因此可以作为一个使用。
这是 std::ostream_iterator::operator=
的实现来自 libstdc++:
/// 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
, 它也被插入到 _M_stream
中.然后它返回。
关于c++ - Exception C++ 第 1 章第 1 部分中的 copy() 算法如何使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21903477/