为什么矢量模板函数赋值有两个版本来区分

时间:2015-06-23 07:10:45

标签: c++ stl iterator

我正在阅读SGI STL的源代码。当我读取assign实现的源代码时,我发现有两个版本,一个用于输入迭代,另一个用于转发迭代器。我知道输入迭代器支持read和++,转发迭代器支持读写和++,为什么它有两个版本用于输入和转发迭代器?

template <class _Tp, class _Alloc> template <class _InputIter>
void vector<_Tp, _Alloc>::_M_assign_aux(_InputIter __first, _InputIter __last,
                                    input_iterator_tag) {
  iterator __cur = begin();
  for ( ; __first != __last && __cur != end(); ++__cur, ++__first)
    *__cur = *__first;
  if (__first == __last)
    erase(__cur, end());
  else
    insert(end(), __first, __last);
}

template <class _Tp, class _Alloc> template <class _ForwardIter>
void
vector<_Tp, _Alloc>::_M_assign_aux(_ForwardIter __first, _ForwardIter __last,
                               forward_iterator_tag) {
  size_type __len = 0;
  distance(__first, __last, __len);

  if (__len > capacity()) {
    iterator __tmp = _M_allocate_and_copy(__len, __first, __last);
    destroy(_M_start, _M_finish);
    _M_deallocate(_M_start, _M_end_of_storage - _M_start);
    _M_start = __tmp;
    _M_end_of_storage = _M_finish = _M_start + __len;
  }
  else if (size() >= __len) {
    iterator __new_finish = copy(__first, __last, _M_start);
    destroy(__new_finish, _M_finish);
    _M_finish = __new_finish;
  }
  else {
    _ForwardIter __mid = __first;
    advance(__mid, size());
    copy(__first, __mid, _M_start);
    _M_finish = uninitialized_copy(__mid, __last, _M_finish);
  }
}

1 个答案:

答案 0 :(得分:6)

  

我知道输入迭代器支持read和++,转发迭代器   支持读写和++

不完全。这里的关键点是前向迭代器是 multipass 。您只能迭代(非前向)输入迭代器一次,而您可以多次遍历前向迭代器。

这意味着使用前向迭代器,可以使用distance()提前获取新范围内的元素数,在需要时分配必要的内存量,然后再次迭代该范围复制元素。这可以保证您最多重新分配一次。

使用输入迭代器,您无法执行此操作,因为distance()调用将在范围内迭代,并且您无法再次迭代它以实际读取元素。