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)