STL(九)之iterator C++标准库(九)之iterator

C++标准库(九)之iterator

iterator

iterator模式:提供一种方法,使之能依次访问容器内的各个元素,而又不暴露该聚合物内部的表述方式。
STL的中心思想是将算法与数据结构分离,彼此独立设计,最后在用iterator将他们结合在一起,获得最大的适配性。

vector

设计理念

vector是动态空间,随着元素的加入,内部机制会自动扩充空间以容纳新元素。vector的实现技术核心在于:对容器大小的控制以及重新配置时数据的移动效率
空间配置策略:在原容器无可用空间时,将容器大小扩展为原先的两倍,然后将原先的数据copy,在copy的数据后面构造新元素。
数据移动效率:根据是否为POD类型判断移动数据的成本,并想进一切方法减少数据移动的次数,源码中有详解。

迭代器定义

vector在进行萃取的时候,会使用萃取提供的特化版本:template<typename T> struct iterator_traits<T*> {}

template<typename T,class Alloc=alloc> class vector { public: typedef T value_type; typedef value_type* pointer; typedef value_type* iterator; typedef value_type& reference; typedef size_t size_type; typedef ptrdiff_t difference_type; protected: iterator begin; iterator end; //使用空间的尾部 iterator end_of_storage; //可用空间的尾部 };

迭代器失效分析

  • 增加/删除当前的iterator,当前iterator后面的iterator都会失效
  • 当增加元素的时候,因为扩容,可能会使原先的迭代器全部失效

list

设计理念

SGI STL的list是不仅是双向链表,还是一个环形链表,存在一个额外的尾部结点,遵守STL算法左闭右开的要求。

迭代器定义

template<typename T>
struct __list_node { typedef void* void_pointer; void_pointer prev; void_pointer next; T data; }; template<typename T,typename ref,typename ptr> struct __list_iterator { typedef __list_iterator<T,T&,T*> iterator; typedef __list_iterator<T,ref,ptr> self; typedef bidirectional_iterator_tag iterator_category; typedef T value; typedef ptr pointer; typedef ref reference; typedef __list_node<T>* link_type; typedef size_t size_type; typedef ptrdiff_t difference_type; link_type node; __list_iterator(link_type type) : node(type) {}; __list_iterator() {}; __list_iterator(const __list_iterator& iter) : node(iter.node) {}; bool operator==(const self& iter) const {return iter.node == node;}; bool operator!=(const self& iter) const {return iter.node != node;}; reference operator*() const {return ((*node).data;}; pointer operator->() const {return &(operator*());}; self& operator++() { node = (link_type)((*node).next); return *this; } slef operator++(int) { self temp = *this; ++*this; return temp; } self& operator() { node = (link_type)((*node).prev); return *this; } slef operator++(int) { self temp = *this; --*this; return temp; } } template<typename T,class Alloc=alloc> class list { protected: typedef void* _Void_pointer; public: typedef _Tp value_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; typedef _List_node<_Tp> _Node; typedef size_t size_type; typedef ptrdiff_t difference_type; public: typedef _List_iterator<_Tp,_Tp&,_Tp*> iterator; typedef _List_iterator<_Tp,const _Tp&,const _Tp*> const_iterator; } 

迭代器失效分析

  • 插入或者删除都不会导致迭代器失效

    deque

    设计理念

    deque允许在常数时间内对头端的元素进入插入或者删除,因为他是动态的以连续分段的空间组成的,访问的复杂度由迭代器去维护。这里的map是由一小块连续空间,其中每个元素都是指针,指向一小段连续空间,其中每个元素都是指针,指向另一段连续线性空间,成为缓冲区,默认值为512bytes。
    一个deque至少会管理8个节点,最多是“所需节点数+2”。在结点数已经用完的情况下,重新换一个map。
    删除或者插入的方式:如果清除/插入点之前的元素较少,就移动清除点之前的元素;反之,移动清除/插入点之后的元素

    迭代器定义

    deque是连续分段空间,维持其在“整体连续”假象的任务,落在了迭代器operator++和operator--两个运算子身上。
template <class _Tp, class _Ref, class _Ptr> struct _Deque_iterator { typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator; typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); } typedef random_access_iterator_tag iterator_category; typedef _Tp value_type; typedef _Ptr pointer; typedef _Ref reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef _Tp** _Map_pointer; typedef _Deque_iterator _Self; _Tp* _M_cur; _Tp* _M_first; _Tp* _M_last; _Map_pointer _M_node; _Deque_iterator(_Tp* __x, _Map_pointer __y) : _M_cur(__x), _M_first(*__y), _M_last(*__y + _S_buffer_size()), _M_node(__y) {} _Deque_iterator() : _M_cur(0), _M_first(0), _M_last(0), _M_node(0) {} _Deque_iterator(const iterator& __x) : _M_cur(__x._M_cur), _M_first(__x._M_first), _M_last(__x._M_last), _M_node(__x._M_node) {} reference operator*() const { return *_M_cur; } #ifndef __SGI_STL_NO_ARROW_OPERATOR pointer operator->() const { return _M_cur; } #endif /* __SGI_STL_NO_ARROW_OPERATOR */ difference_type operator-(const _Self& __x) const { return difference_type(_S_buffer_size()) * (_M_node - __x._M_node - 1) + (_M_cur - _M_first) + (__x._M_last - __x._M_cur); } _Self& operator++() { ++_M_cur; if (_M_cur == _M_last) { _M_set_node(_M_node + 1); _M_cur = _M_first; } return *this; } _Self operator++(int) { _Self __tmp = *this; ++*this; return __tmp; } _Self& operator--() { if (_M_cur == _M_first) { _M_set_node(_M_node - 1); _M_cur = _M_last; } --_M_cur; return *this; } _Self operator--(int) { _Self __tmp = *this; --*this; return __tmp; } _Self& operator+=(difference_type __n) { difference_type __offset = __n + (_M_cur - _M_first); if (__offset >= 0 && __offset < difference_type(_S_buffer_size())) _M_cur += __n; else { difference_type __node_offset = __offset > 0 ? __offset / difference_type(_S_buffer_size()) : -difference_type((-__offset - 1) / _S_buffer_size()) - 1; _M_set_node(_M_node + __node_offset); _M_cur = _M_first + (__offset - __node_offset * difference_type(_S_buffer_size())); } return *this; } _Self operator+(difference_type __n) const { _Self __tmp = *this; return __tmp += __n; } _Self& operator-=(difference_type __n) { return *this += -__n; } _Self operator-(difference_type __n) const { _Self __tmp = *this; return __tmp -= __n; } reference operator[](difference_type __n) const { return *(*this + __n); } bool operator==(const _Self& __x) const { return _M_cur == __x._M_cur; } bool operator!=(const _Self& __x) const { return !(*this == __x); } bool operator<(const _Self& __x) const { return (_M_node == __x._M_node) ? (_M_cur < __x._M_cur) : (_M_node < __x._M_node); } bool operator>(const _Self& __x) const { return __x < *this; } bool operator<=(const _Self& __x) const { return !(__x < *this); } bool operator>=(const _Self& __x) const { return !(*this < __x); } void _M_set_node(_Map_pointer __new_node) { _M_node = __new_node; _M_first = *__new_node; _M_last = _M_first + difference_type(_S_buffer_size()); } }; template <class _Tp, class _Ref, class _Ptr> inline _Deque_iterator<_Tp, _Ref, _Ptr> operator+(ptrdiff_t __n, const _Deque_iterator<_Tp, _Ref, _Ptr>& __x) { return __x + __n; } template<typename T,typename Alloc=alloc,size_t Bufsize = 0> class deque { public: typedef T value_type; typede value_type* pointer; typedef size_t size_type; typedef __deque_iterator<T,T&,T*,BufSize> iterator; protected: typedef pointer* map_pointer; iterator begin; iterator end; map_iterator map; size_type map_size; }

迭代器失效分析

  • 插入时,可能会更换map,使得存在的所有迭代器失效
  • 删除时,使当前iterator之后/之前的迭代器失效,根据前后元素量的多少决定。

    set和multiset

    设计理念

    在SGI STL中,set底层使用红黑树完成,set中所有的元素都是自动排列的,在set中:value = key,并且,set中的值不允许修改。
    set与multiset的区别在于使用红黑树的底层插入操作不同:insert_equal()insert_unique()

    迭代器定义

    迭代器的++和--操作是以中序遍历的过程进行的。
template<typename Key, typename Compare = less<Key>, class Alloc = alloc>
class set
{
    public: typedef Key key_type; typedef Key value_type; typedef rb_tree<key_type,value_type,identity<value_type>,key_compare,Alloc> rep_type; typedef typename rep_type::const_pointer pointer; typedef typename rep_type::const_pointer const_pointer; typedef typename rep_type::const_reference reference; typedef typename rep_type::const_reference const_reference; typedef typename rep_type::const_iterator iterator; typedef typename rep_type::const_iterator const_iterator; private: rep_type rep; }

迭代器失效分析

基本上删除和插入操作都不会使迭代器失效。

map和multimap

设计理念

在SGI STL中,map底层使用红黑树完成。所有的元素都会根据元素的键值自动排序。map的所有元素都是pair,同时拥有value可key。
map与multimap的区别在于使用红黑树的底层插入操作不同:insert_equal()insert_unique()

迭代器定义

迭代器的++和--操作是以中序遍历的过程进行的。

template<typename T1,typename T2>
struct pair { typedef T1 first_type; typedef T2 second_type; T1 first; T2 second; }; template<typename Key,typename Value,typename Compare = less<Key>, class Alloc=alloc> class map { public: typedef Key key_type; typedef Value value_type; typedef Value mapped_type; typedef pair<const Key,Value> value_type; typedef Compare key_conpare; typedef rb_tree<key_type,value_type,select1st<value_type>,key_compare,Alloc> rep_type; typedef typename rep_type::pointer pointer; typedef typename rep_type::const_pointer const_pointer; typedef typaneme rep_type::iterator iterator; typedef typaneme rep_type::const_iterator const_iterator; private: rep_type rep; };

迭代器失效分析

基本上删除和插入操作不会使迭代器失效。

iterator

iterator模式:提供一种方法,使之能依次访问容器内的各个元素,而又不暴露该聚合物内部的表述方式。
STL的中心思想是将算法与数据结构分离,彼此独立设计,最后在用iterator将他们结合在一起,获得最大的适配性。

vector

设计理念

vector是动态空间,随着元素的加入,内部机制会自动扩充空间以容纳新元素。vector的实现技术核心在于:对容器大小的控制以及重新配置时数据的移动效率
空间配置策略:在原容器无可用空间时,将容器大小扩展为原先的两倍,然后将原先的数据copy,在copy的数据后面构造新元素。
数据移动效率:根据是否为POD类型判断移动数据的成本,并想进一切方法减少数据移动的次数,源码中有详解。

迭代器定义

vector在进行萃取的时候,会使用萃取提供的特化版本:template<typename T> struct iterator_traits<T*> {}

template<typename T,class Alloc=alloc> class vector { public: typedef T value_type; typedef value_type* pointer; typedef value_type* iterator; typedef value_type& reference; typedef size_t size_type; typedef ptrdiff_t difference_type; protected: iterator begin; iterator end; //使用空间的尾部 iterator end_of_storage; //可用空间的尾部 };

迭代器失效分析

  • 增加/删除当前的iterator,当前iterator后面的iterator都会失效
  • 当增加元素的时候,因为扩容,可能会使原先的迭代器全部失效

list

设计理念

SGI STL的list是不仅是双向链表,还是一个环形链表,存在一个额外的尾部结点,遵守STL算法左闭右开的要求。

迭代器定义

template<typename T>
struct __list_node { typedef void* void_pointer; void_pointer prev; void_pointer next; T data; }; template<typename T,typename ref,typename ptr> struct __list_iterator { typedef __list_iterator<T,T&,T*> iterator; typedef __list_iterator<T,ref,ptr> self; typedef bidirectional_iterator_tag iterator_category; typedef T value; typedef ptr pointer; typedef ref reference; typedef __list_node<T>* link_type; typedef size_t size_type; typedef ptrdiff_t difference_type; link_type node; __list_iterator(link_type type) : node(type) {}; __list_iterator() {}; __list_iterator(const __list_iterator& iter) : node(iter.node) {}; bool operator==(const self& iter) const {return iter.node == node;}; bool operator!=(const self& iter) const {return iter.node != node;}; reference operator*() const {return ((*node).data;}; pointer operator->() const {return &(operator*());}; self& operator++() { node = (link_type)((*node).next); return *this; } slef operator++(int) { self temp = *this; ++*this; return temp; } self& operator() { node = (link_type)((*node).prev); return *this; } slef operator++(int) { self temp = *this; --*this; return temp; } } template<typename T,class Alloc=alloc> class list { protected: typedef void* _Void_pointer; public: typedef _Tp value_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; typedef _List_node<_Tp> _Node; typedef size_t size_type; typedef ptrdiff_t difference_type; public: typedef _List_iterator<_Tp,_Tp&,_Tp*> iterator; typedef _List_iterator<_Tp,const _Tp&,const _Tp*> const_iterator; } 

迭代器失效分析

  • 插入或者删除都不会导致迭代器失效

    deque

    设计理念

    deque允许在常数时间内对头端的元素进入插入或者删除,因为他是动态的以连续分段的空间组成的,访问的复杂度由迭代器去维护。这里的map是由一小块连续空间,其中每个元素都是指针,指向一小段连续空间,其中每个元素都是指针,指向另一段连续线性空间,成为缓冲区,默认值为512bytes。
    一个deque至少会管理8个节点,最多是“所需节点数+2”。在结点数已经用完的情况下,重新换一个map。
    删除或者插入的方式:如果清除/插入点之前的元素较少,就移动清除点之前的元素;反之,移动清除/插入点之后的元素

    迭代器定义

    deque是连续分段空间,维持其在“整体连续”假象的任务,落在了迭代器operator++和operator--两个运算子身上。
template <class _Tp, class _Ref, class _Ptr> struct _Deque_iterator { typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator; typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); } typedef random_access_iterator_tag iterator_category; typedef _Tp value_type; typedef _Ptr pointer; typedef _Ref reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef _Tp** _Map_pointer; typedef _Deque_iterator _Self; _Tp* _M_cur; _Tp* _M_first; _Tp* _M_last; _Map_pointer _M_node; _Deque_iterator(_Tp* __x, _Map_pointer __y) : _M_cur(__x), _M_first(*__y), _M_last(*__y + _S_buffer_size()), _M_node(__y) {} _Deque_iterator() : _M_cur(0), _M_first(0), _M_last(0), _M_node(0) {} _Deque_iterator(const iterator& __x) : _M_cur(__x._M_cur), _M_first(__x._M_first), _M_last(__x._M_last), _M_node(__x._M_node) {} reference operator*() const { return *_M_cur; } #ifndef __SGI_STL_NO_ARROW_OPERATOR pointer operator->() const { return _M_cur; } #endif /* __SGI_STL_NO_ARROW_OPERATOR */ difference_type operator-(const _Self& __x) const { return difference_type(_S_buffer_size()) * (_M_node - __x._M_node - 1) + (_M_cur - _M_first) + (__x._M_last - __x._M_cur); } _Self& operator++() { ++_M_cur; if (_M_cur == _M_last) { _M_set_node(_M_node + 1); _M_cur = _M_first; } return *this; } _Self operator++(int) { _Self __tmp = *this; ++*this; return __tmp; } _Self& operator--() { if (_M_cur == _M_first) { _M_set_node(_M_node - 1); _M_cur = _M_last; } --_M_cur; return *this; } _Self operator--(int) { _Self __tmp = *this; --*this; return __tmp; } _Self& operator+=(difference_type __n) { difference_type __offset = __n + (_M_cur - _M_first); if (__offset >= 0 && __offset < difference_type(_S_buffer_size())) _M_cur += __n; else { difference_type __node_offset = __offset > 0 ? __offset / difference_type(_S_buffer_size()) : -difference_type((-__offset - 1) / _S_buffer_size()) - 1; _M_set_node(_M_node + __node_offset); _M_cur = _M_first + (__offset - __node_offset * difference_type(_S_buffer_size())); } return *this; } _Self operator+(difference_type __n) const { _Self __tmp = *this; return __tmp += __n; } _Self& operator-=(difference_type __n) { return *this += -__n; } _Self operator-(difference_type __n) const { _Self __tmp = *this; return __tmp -= __n; } reference operator[](difference_type __n) const { return *(*this + __n); } bool operator==(const _Self& __x) const { return _M_cur == __x._M_cur; } bool operator!=(const _Self& __x) const { return !(*this == __x); } bool operator<(const _Self& __x) const { return (_M_node == __x._M_node) ? (_M_cur < __x._M_cur) : (_M_node < __x._M_node); } bool operator>(const _Self& __x) const { return __x < *this; } bool operator<=(const _Self& __x) const { return !(__x < *this); } bool operator>=(const _Self& __x) const { return !(*this < __x); } void _M_set_node(_Map_pointer __new_node) { _M_node = __new_node; _M_first = *__new_node; _M_last = _M_first + difference_type(_S_buffer_size()); } }; template <class _Tp, class _Ref, class _Ptr> inline _Deque_iterator<_Tp, _Ref, _Ptr> operator+(ptrdiff_t __n, const _Deque_iterator<_Tp, _Ref, _Ptr>& __x) { return __x + __n; } template<typename T,typename Alloc=alloc,size_t Bufsize = 0> class deque { public: typedef T value_type; typede value_type* pointer; typedef size_t size_type; typedef __deque_iterator<T,T&,T*,BufSize> iterator; protected: typedef pointer* map_pointer; iterator begin; iterator end; map_iterator map; size_type map_size; }

迭代器失效分析

  • 插入时,可能会更换map,使得存在的所有迭代器失效
  • 删除时,使当前iterator之后/之前的迭代器失效,根据前后元素量的多少决定。

    set和multiset

    设计理念

    在SGI STL中,set底层使用红黑树完成,set中所有的元素都是自动排列的,在set中:value = key,并且,set中的值不允许修改。
    set与multiset的区别在于使用红黑树的底层插入操作不同:insert_equal()insert_unique()

    迭代器定义

    迭代器的++和--操作是以中序遍历的过程进行的。
template<typename Key, typename Compare = less<Key>, class Alloc = alloc>
class set
{
    public: typedef Key key_type; typedef Key value_type; typedef rb_tree<key_type,value_type,identity<value_type>,key_compare,Alloc> rep_type; typedef typename rep_type::const_pointer pointer; typedef typename rep_type::const_pointer const_pointer; typedef typename rep_type::const_reference reference; typedef typename rep_type::const_reference const_reference; typedef typename rep_type::const_iterator iterator; typedef typename rep_type::const_iterator const_iterator; private: rep_type rep; }

迭代器失效分析

基本上删除和插入操作都不会使迭代器失效。

map和multimap

设计理念

在SGI STL中,map底层使用红黑树完成。所有的元素都会根据元素的键值自动排序。map的所有元素都是pair,同时拥有value可key。
map与multimap的区别在于使用红黑树的底层插入操作不同:insert_equal()insert_unique()

迭代器定义

迭代器的++和--操作是以中序遍历的过程进行的。

template<typename T1,typename T2>
struct pair { typedef T1 first_type; typedef T2 second_type; T1 first; T2 second; }; template<typename Key,typename Value,typename Compare = less<Key>, class Alloc=alloc> class map { public: typedef Key key_type; typedef Value value_type; typedef Value mapped_type; typedef pair<const Key,Value> value_type; typedef Compare key_conpare; typedef rb_tree<key_type,value_type,select1st<value_type>,key_compare,Alloc> rep_type; typedef typename rep_type::pointer pointer; typedef typename rep_type::const_pointer const_pointer; typedef typaneme rep_type::iterator iterator; typedef typaneme rep_type::const_iterator const_iterator; private: rep_type rep; };

迭代器失效分析

基本上删除和插入操作不会使迭代器失效。

猜你喜欢

转载自www.cnblogs.com/xcb-1024day/p/11332510.html