STL 源码剖析 -- Iterator 迭代器全揭秘
1、iterator_tag
iterator_tag 标记了 iterator 的类型。
/// Marking input iterators.
struct input_iterator_tag { };
/// Marking output iterators.
struct output_iterator_tag { };
/// Forward iterators support a superset of input iterator operations.
struct forward_iterator_tag : public input_iterator_tag { };
/// Bidirectional iterators support a superset of forward iterator
/// operations.
struct bidirectional_iterator_tag : public forward_iterator_tag { };
/// Random-access iterators support a superset of bidirectional
/// iterator operations.
struct random_access_iterator_tag : public bidirectional_iterator_tag { };
2、iterator
每个 iterator 都必须提供以下 5 中数据类型
- iterator_category
- value_type
- difference_type
- pointer
- reference
template<typename _Category, typename _Tp, typename _Distance = ptrdiff_t,
typename _Pointer = _Tp*, typename _Reference = _Tp&>
struct _GLIBCXX17_DEPRECATED iterator
{
/// One of the @link iterator_tags tag types@endlink.
typedef _Category iterator_category;
/// The type "pointed to" by the iterator.
typedef _Tp value_type;
/// Distance between iterators is represented as this type.
typedef _Distance difference_type;
/// This type represents a pointer-to-value_type.
typedef _Pointer pointer;
/// This type represents a reference-to-value_type.
typedef _Reference reference;
};
3、iterator_traits
iterator_traits 是为了兼容原生指针(原生指针没有定义上述 5 中数据类型)
template<typename _Iterator>
struct __iterator_traits<_Iterator,
__void_t<typename _Iterator::iterator_category,
typename _Iterator::value_type,
typename _Iterator::difference_type,
typename _Iterator::pointer,
typename _Iterator::reference>>
{
typedef typename _Iterator::iterator_category iterator_category;
typedef typename _Iterator::value_type value_type;
typedef typename _Iterator::difference_type difference_type;
typedef typename _Iterator::pointer pointer;
typedef typename _Iterator::reference reference;
};
template<typename _Iterator>
struct iterator_traits
: public __iterator_traits<_Iterator> { };
iterator_traits 使用偏特化的方法,对于原生指针,也定义了 Iterator 的 5 中数据类型。
template<typename _Tp>
struct iterator_traits<_Tp*>
{
typedef random_access_iterator_tag iterator_category;
typedef _Tp value_type;
typedef ptrdiff_t difference_type;
typedef _Tp* pointer;
typedef _Tp& reference;
};
/// Partial specialization for const pointer types.
template<typename _Tp>
struct iterator_traits<const _Tp*>
{
typedef random_access_iterator_tag iterator_category;
typedef _Tp value_type;
typedef ptrdiff_t difference_type;
typedef const _Tp* pointer;
typedef const _Tp& reference;
};
4、std::distance()/std::advance()
4.1、std::distance()
std::distance() 计算 first 到 last 的距离。不同的 iterator_tag 支持的操作不同,计算方法也不同。
template<typename _InputIterator>
_GLIBCXX_NODISCARD
inline _GLIBCXX17_CONSTEXPR
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));
}
input_iterator_tag 每次只能移动一步,循环直到 first == last,返回距离。
template<typename _InputIterator>
inline _GLIBCXX14_CONSTEXPR
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;
}
如果是 random_access_iterator_tag,直接 last - first 返回结果
template<typename _RandomAccessIterator>
inline _GLIBCXX14_CONSTEXPR
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;
}
output_iterator_tag 是不支持 std::distance() 计算
template<typename _OutputIterator>
void
__distance(_OutputIterator, _OutputIterator, output_iterator_tag) = delete;
4.2、std::advance()
std::advance() 将 first 移动 n 个位置。
template<typename _InputIterator, typename _Distance>
inline _GLIBCXX17_CONSTEXPR void
advance(_InputIterator& __i, _Distance __n)
{
// concept requirements -- taken care of in __advance
typename iterator_traits<_InputIterator>::difference_type __d = __n;
std::__advance(__i, __d, std::__iterator_category(__i));
}
如果是 input_iterator_tag,仅仅支持正向移动,每次移动一步。
template<typename _InputIterator, typename _Distance>
inline _GLIBCXX14_CONSTEXPR void
__advance(_InputIterator& __i, _Distance __n, input_iterator_tag)
{
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
__glibcxx_assert(__n >= 0);
while (__n--)
++__i;
}
bidirectional_iterator_tag 支持正向和反向移动。
template<typename _BidirectionalIterator, typename _Distance>
inline _GLIBCXX14_CONSTEXPR void
__advance(_BidirectionalIterator& __i, _Distance __n,
bidirectional_iterator_tag)
{
// concept requirements
__glibcxx_function_requires(_BidirectionalIteratorConcept<
_BidirectionalIterator>)
if (__n > 0)
while (__n--)
++__i;
else
while (__n++)
--__i;
}
random_access_iterator_tag 直接通过 + 计算
template<typename _RandomAccessIterator, typename _Distance>
inline _GLIBCXX14_CONSTEXPR void
__advance(_RandomAccessIterator& __i, _Distance __n,
random_access_iterator_tag)
{
// concept requirements
__glibcxx_function_requires(_RandomAccessIteratorConcept<
_RandomAccessIterator>)
if (__builtin_constant_p(__n) && __n == 1)
++__i;
else if (__builtin_constant_p(__n) && __n == -1)
--__i;
else
__i += __n;
}
5、insert_iterator
insert_iterator 构造于容器之上,将 iterator 的赋值操作,转换为容器的插入操作。
5.1、back_insert_iterator
back_insert_iterator 的赋值操作,转换为容器末尾的插入。
back_insert_iterator 属于 output_iterator_tag
template<typename _Container>
class back_insert_iterator
: public iterator<output_iterator_tag, void, void, void, void>
{
protected:
_Container* container;
/* ... */
};
operator=() 调用容器 push_back() 函数在末尾插入元素。
_GLIBCXX20_CONSTEXPR
back_insert_iterator&
operator=(const typename _Container::value_type& __value)
{
container->push_back(__value);
return *this;
}
_GLIBCXX20_CONSTEXPR
back_insert_iterator&
operator=(typename _Container::value_type&& __value)
{
container->push_back(std::move(__value));
return *this;
}
函数 back_inserter() 接受一个容器参数,构造一个 back_insert_iterator 对象。
template<typename _Container>
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
inline back_insert_iterator<_Container>
back_inserter(_Container& __x)
{ return back_insert_iterator<_Container>(__x); }
5.2、front_insert_iterator
front_insert_iterator 和 back_insert_iterator 类似,也是 output_iterator_tag 类型 iterator。
template<typename _Container>
class front_insert_iterator
: public iterator<output_iterator_tag, void, void, void, void>
{
protected:
_Container* container;
/* ... */
};
operator=() 调用容器 push_front() 函数在首部插入元素。
_GLIBCXX20_CONSTEXPR
front_insert_iterator&
operator=(const typename _Container::value_type& __value)
{
container->push_front(__value);
return *this;
}
_GLIBCXX20_CONSTEXPR
front_insert_iterator&
operator=(typename _Container::value_type&& __value)
{
container->push_front(std::move(__value));
return *this;
}
函数 front_inserter() 接受一个容器参数,构造一个 front_insert_iterator对象。
template<typename _Container>
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
inline front_insert_iterator<_Container>
front_inserter(_Container& __x)
{ return front_insert_iterator<_Container>(__x); }
5.3、insert_iterator
insert_iterator 也是 output_iterator_tag 类型迭代器。
template<typename _Container>
class insert_iterator
: public iterator<output_iterator_tag, void, void, void, void>
{
protected:
_Container* container;
_Iter iter;
/* ... */
};
operator=() 调用容器 insert() 函数插入元素。
_GLIBCXX20_CONSTEXPR
insert_iterator&
operator=(const typename _Container::value_type& __value)
{
iter = container->insert(iter, __value);
++iter;
return *this;
}
_GLIBCXX20_CONSTEXPR
insert_iterator&
operator=(typename _Container::value_type&& __value)
{
iter = container->insert(iter, std::move(__value));
++iter;
return *this;
}
函数 inserter() 接受一个容器参数,构造一个 insert_iterator对象。
template<typename _Container>
_GLIBCXX_NODISCARD
inline insert_iterator<_Container>
inserter(_Container& __x, typename _Container::iterator __i)
{ return insert_iterator<_Container>(__x, __i); }
6、iterator adaptor
iterator 适配器将某个 iterator 封装成另一个 iterator,改变了原来 iterator 的行为。
6.1、reverse_iterator
bidirectional_iterator_tag 和 random_access_iterator_tag 都有相应的反向迭代器。
template<typename _Iterator>
class reverse_iterator
: public iterator<typename iterator_traits<_Iterator>::iterator_category,
typename iterator_traits<_Iterator>::value_type,
typename iterator_traits<_Iterator>::difference_type,
typename iterator_traits<_Iterator>::pointer,
typename iterator_traits<_Iterator>::reference>
{
protected:
_Iterator current;
/* ... */
};
如果对 reverse_iterator 执行 ++,则原生 iterator 执行 --,反之亦然。+/- n 也是相同的逻辑。
_GLIBCXX17_CONSTEXPR reverse_iterator&
operator++()
{
--current;
return *this;
}
_GLIBCXX17_CONSTEXPR reverse_iterator
operator++(int)
{
reverse_iterator __tmp = *this;
--current;
return __tmp;
}
_GLIBCXX17_CONSTEXPR reverse_iterator&
operator--()
{
++current;
return *this;
}
_GLIBCXX17_CONSTEXPR reverse_iterator
operator--(int)
{
reverse_iterator __tmp = *this;
++current;
return __tmp;
}
比较反直觉的是 reverse_iterator::operator*()/operator->() 两个函数。返回的 --current 对应的值。因为容器 end() 返回的 iterator 并不是容器的最后一个元素,end() - 1 才是最后一个元素。
_GLIBCXX_NODISCARD
_GLIBCXX17_CONSTEXPR reference
operator*() const
{
_Iterator __tmp = current;
return *--__tmp;
}
_GLIBCXX_NODISCARD
_GLIBCXX17_CONSTEXPR pointer
operator->() const
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 1052. operator-> should also support smart pointers
_Iterator __tmp = current;
--__tmp;
return _S_to_pointer(__tmp);
}
make_reverse_iterator() 函数返回 reverse_iterator 对象。
template<typename _Iterator>
[[__nodiscard__]]
inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator>
make_reverse_iterator(_Iterator __i)
{ return reverse_iterator<_Iterator>(__i); }
6.2、__gnu_cxx::__normal_iterator
__normal_iterator 适配器不会改变底层 iterator 的行为,其目的是将原始指针封装成一个普通的 iterator。
template<typename _Iterator, typename _Container>
class __normal_iterator
{
protected:
_Iterator _M_current;
/* ... */
};
6.3、move_iterator
move_iterator 改变 iterator 解引用返回值类型:返回右值引用类型。
template<typename _Iterator>
class move_iterator
{
_Iterator _M_current;
using __traits_type = iterator_traits<_Iterator>;
#if ! (__cplusplus > 201703L && __cpp_lib_concepts)
using __base_ref = typename __traits_type::reference;
#endif
using reference
= __conditional_t<is_reference<__base_ref>::value,
typename remove_reference<__base_ref>::type&&,
__base_ref>;
/* ... */
};
make_move_iterator() 函数返回一个 move_iterator 对象。
template<typename _Iterator>
[[__nodiscard__]]
inline _GLIBCXX17_CONSTEXPR move_iterator<_Iterator>
make_move_iterator(_Iterator __i)
{ return move_iterator<_Iterator>(std::move(__i)); }
欢迎关注公众号“源知源为”,阅读更多技术干货
#STL##C++零基础学习#C/C++ 语言基础

海康威视公司福利 1182人发布