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--兩個運算子身上。
```
templatetypedef 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 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
template
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
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
T1 first;
T2 second;
};
template<typename Key,typename Value,typename Compare = less
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;
};
```
叠代器失效分析
基本上刪除和插入操作不會使叠代器失效。
C++標準庫(七)之iterator