如何使用Exception C++第1章第1部分中的copy()算法?

Ele*_*rks 0 c++ stl copy vector

Herb提出了一种循环向量的方法:

for(vector<int>::iterator i = v.begin(); i < v.end(); i++) {
 cout << *i << endl;
}
Run Code Online (Sandbox Code Playgroud)

他将此代码替换为:

copy(v.begin(), v.end(), ostream_iterator<int>(cout, "\n"));
Run Code Online (Sandbox Code Playgroud)

我很难理解这是如何工作的,或者为什么会这样.我查找了复制功能,文档说它相当于:

template<class InputIterator, class OutputIterator>
  OutputIterator copy (InputIterator first, InputIterator last, 
                       OutputIterator result)
{
  while (first!=last) {
    *result = *first;
    ++result; ++first;
  }
  return result;
}
Run Code Online (Sandbox Code Playgroud)

所以我提出了一个问题,"当我们*OutputIterator会发生什么?"

reference operator*() const;

Dereference iterator
Returns *this.
Run Code Online (Sandbox Code Playgroud)

这就是我感到困惑的地方.我没有看到OutputIterator指向的定义.另外,我没有看到该行如何 *result = *first;可能转换为调用cout << *i;

Jos*_*eld 5

你只是查找了它的OutputIterator作用.OutputIterator只是标准库中的一堆类型满足的一组要求.其中一种类型是std::ostream_iterator,所以你需要看看它在上下文中的表现std::copy.

所以在复制算法中,我们正在做*result = *first.首先,operator*for std::ostream_iterator不执行任何操作 - 它只返回迭代器本身.当我们分配给这个迭代器时,会发生魔力.如果你向上看std::ostream_iterator::operator=,你会看到分配给这个迭代器会将(使用<<)插入到它构造的流中.因此,您案例中的作业将流入std::cout.

在此之后,双方resultfirst递增.递增result(std::ostream_iterator)没有效果,递增first将移动到向量中的下一个元素.然后在下一次迭代中,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;
}
Run Code Online (Sandbox Code Playgroud)

忽略第一行的断言,我们可以看到它然后插入__value其内部_M_stream流.然后,如果有分隔符集_M_string,它也会被插入_M_stream.然后它返回.