C++ Notes: iterator 加减运算

不是所有的迭代器都支持加减运算。

std::list<int> iList{1, 2, 3, 4};

auto iSize = iList.end() - iList.begin();
// error: no match for 'operator-' (operand types are 'std::list<int>::iterator {aka std::_List_iterator<int>}'
// and 'std::list<int>::iterator {aka std::_List_iterator<int>}')

因为std::list是双向迭代器BidirectionalIterator,双向迭代器不只支持+, -操作,只支持++, --操作。只有随机访问迭代器RandomAccessIterator支持+, -操作。

要获得两个迭代器直接的差值可以使用std::distance()

auto iSize = std::distance(iList.begin(), iList.end());

实际上,std::distance()对于双向迭代器就是遍历一遍,返回遍历次数;对于随机访问迭代器就是简单的首尾迭代器相减。

template<typename _InputIterator>
  inline typename iterator_traits<_InputIterator>::difference_type
  distance(_InputIterator __first, _InputIterator __last)
  {
    // concept requirements -- taken care of in __distance
    return std::__distance(__first, __last,
             std::__iterator_category(__first));
  }

// 遍历迭代器
template<typename _InputIterator>
  inline typename iterator_traits<_InputIterator>::difference_type
  __distance(_InputIterator __first, _InputIterator __last,
             input_iterator_tag)
  {
    // concept requirements
    __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)

    typename iterator_traits<_InputIterator>::difference_type __n = 0;
    while (__first != __last)
        {
          ++__first;
          ++__n;
        }
    return __n;
  }

// 迭代器相减
template<typename _RandomAccessIterator>
  inline typename iterator_traits<_RandomAccessIterator>::difference_type
  __distance(_RandomAccessIterator __first, _RandomAccessIterator __last,
             random_access_iterator_tag)
  {
    // concept requirements
    __glibcxx_function_requires(_RandomAccessIteratorConcept<
                  _RandomAccessIterator>)
    return __last - __first;
  }

另外,对于STL容器的size()操作也是一样的

// std::list的size()操作即遍历迭代器
/**  Returns the number of elements in the %list.  */
size_type
size() const _GLIBCXX_NOEXCEPT
{ return this->_M_node_count(); }

// count the number of nodes
size_t _M_node_count() const
{
        return _S_distance(_M_impl._M_node._M_next,
        std::__addressof(_M_impl._M_node));
}

static size_t
_S_distance(const __detail::_List_node_base* __first,
    const __detail::_List_node_base* __last)
{
        size_t __n = 0;
        while (__first != __last)
        {
          __first = __first->_M_next;
          ++__n;
        }
        return __n;
}

// std::vector的size()操作即迭代器相减
/**  Returns the number of elements in the %vector.  */
size_type
size() const _GLIBCXX_NOEXCEPT
{ return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); }

PS:随机访问迭代器 std::vector, std::deque, std::array

双向迭代器 std::list, std::set, std::multiset, std::map, std::mutimap

前向迭代器 std::forward_lsit, std::unordered_set, std::unordered_map, std::unordered_multiset, std::unordered_muiltimap

PPS:前向迭代器和双向迭代器一样,不支持+, -运算,需要使用std::distance()

PPPS: std::forward_list没有提供size()成员。(why