1. 程式人生 > >STL源代碼剖析 容器 stl_deque.h

STL源代碼剖析 容器 stl_deque.h

pen -c locate 概念 style 上一個 struct emp ref

本文為senlie原創。轉載請保留此地址:http://blog.csdn.net/zhengsenlie


deque

------------------------------------------------------------------------
??一直看不懂 operator->() 。不明確它為什麽不用接受參數。直接 return &(operator*())
好像我們用叠代器的時候也不沒怎麽用到這個函數,甚至我都不會用


1.概述
vector 是單向開口的連續線性空間。deque 則是一種雙向開口的連續線性空間
同意常數時間內對起頭端進行元素的插入和移除操作
沒有容量概念。由於它是動態地以分段連續空間組合而成,隨時能夠添加一段新的空間並鏈接起來
deque 的叠代器不是普通指針,如非必要。應選擇 vector 而非 deque
對deque 排序,可將 deque 先完整拷貝到一個 vector 身上,將 vector 排序後,再復制回 deque
圖 4-9

2.deque 的中控器
map (不是 STL 裏的 map 容器) --> 主控,是一小塊連續空間。每一個元素指向還有一段較大的連續空間 node-buffer
node-buffer --> 存儲空間主體
圖 4-10
3.叠代器
cur --> 指出分段連續空間在哪裏
first, last --> 推斷自己是否已經處於緩沖區的邊緣
node --> 在緩沖區邊緣前進或後退時必須知道中控器在哪
圖4-11
圖4-12



#ifndef __SGI_STL_INTERNAL_DEQUE_H
#define __SGI_STL_INTERNAL_DEQUE_H


__STL_BEGIN_NAMESPACE 


#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma set woff 1174
#endif


// Note: this function is simply a kludge to work around several compilers'
//  bugs in handling constant expressions.
// 決定緩沖區大小
// 假設 n 不為 0。傳回n ,表示 buffer size 由用戶自己定義
// 假設 n 為 0,表示 buffer size 使用默認值,那麽
// 	 假設 sz(元素大小,sizeof(value_type))小於512,返回 512/sz,
//	 假設 sz不小於 512。返回 1
inline size_t __deque_buf_size(size_t n, size_t sz)
{
  return n != 0 ? n : (sz < 512 ? size_t(512 / sz) : size_t(1));
}


#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG
template <class T, class Ref, class Ptr, size_t BufSiz>
struct __deque_iterator {
  typedef __deque_iterator<T, T&, T*, BufSiz>             iterator;
  typedef __deque_iterator<T, const T&, const T*, BufSiz> const_iterator;
  static size_t buffer_size() {return __deque_buf_size(BufSiz, sizeof(T)); }
#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */
template <class T, class Ref, class Ptr>
struct __deque_iterator {
  typedef __deque_iterator<T, T&, T*>             iterator;
  typedef __deque_iterator<T, const T&, const T*> const_iterator;
  static size_t buffer_size() {return __deque_buf_size(0, sizeof(T)); }
#endif


  typedef random_access_iterator_tag iterator_category;
  typedef T value_type;
  typedef Ptr pointer;
  typedef Ref reference;
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;
  typedef T** map_pointer;


  typedef __deque_iterator self;


  T* cur; //指向緩沖區的現行元素
  T* first; //指向緩沖區的頭
  T* last; // 指向緩沖區的尾
   
  map_pointer node; //指向中控器


  __deque_iterator(T* x, map_pointer y) 
    : cur(x), first(*y), last(*y + buffer_size()), node(y) {}
  __deque_iterator() : cur(0), first(0), last(0), node(0) {}
  __deque_iterator(const iterator& x)
    : cur(x.cur), first(x.first), last(x.last), node(x.node) {}
  //解引用	
  reference operator*() const { return *cur; }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
  //??好像沒用過這東西
  pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
  //兩個叠代器之間的距離
  difference_type operator-(const self& x) const {
    return difference_type(buffer_size()) * (node - x.node - 1) +
      (cur - first) + (x.last - x.cur);
  }
  //前置++
  self& operator++() {
    ++cur;					//切換至下一個元素
    if (cur == last) {		//假設已達到所在緩沖區的尾端
      set_node(node + 1);	//就切換至下一緩沖區的第一個元素
      cur = first;
    }
    return *this; 
  }
  //後置++
  self operator++(int)  {
    self tmp = *this;
    ++*this;				//調用前置++ 完畢前進 ?

--> yes return tmp; } //前置-- self& operator--() { if (cur == first) { set_node(node - 1); cur = last; } --cur; return *this; } //後置-- self operator--(int) { self tmp = *this; --*this; return tmp; } //隨機存取 self& operator+=(difference_type n) { difference_type offset = n + (cur - first); //目標位置在同一緩沖區 if (offset >= 0 && offset < difference_type(buffer_size())) cur += n; //目標位置在不同緩沖區 else { difference_type node_offset = offset > 0 ? offset / difference_type(buffer_size()) : -difference_type((-offset - 1) / buffer_size()) - 1; //切換至正確的節點(緩沖區) set_node(node + node_offset); //切換至正確的元素 cur = first + (offset - node_offset * difference_type(buffer_size())); } return *this; } self operator+(difference_type n) const { self tmp = *this; return tmp += n; //? 不懂為什麽是對 暫時變量 調用 operator+= --> 由於是 operator+,本來就不用改變 this 指向的對象 } 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 cur == x.cur; } bool operator!=(const self& x) const { return !(*this == x); } bool operator<(const self& x) const { return (node == x.node) ? (cur < x.cur) : (node < x.node); } //使用 set_node 來跳一個緩沖區 void set_node(map_pointer new_node) { node = new_node; first = *new_node; last = first + difference_type(buffer_size()); } }; #ifndef __STL_CLASS_PARTIAL_SPECIALIZATION #ifndef __STL_NON_TYPE_TMPL_PARAM_BUG template <class T, class Ref, class Ptr, size_t BufSiz> inline random_access_iterator_tag iterator_category(const __deque_iterator<T, Ref, Ptr, BufSiz>&) { return random_access_iterator_tag(); } template <class T, class Ref, class Ptr, size_t BufSiz> inline T* value_type(const __deque_iterator<T, Ref, Ptr, BufSiz>&) { return 0; } template <class T, class Ref, class Ptr, size_t BufSiz> inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, Ptr, BufSiz>&) { return 0; } #else /* __STL_NON_TYPE_TMPL_PARAM_BUG */ template <class T, class Ref, class Ptr> inline random_access_iterator_tag iterator_category(const __deque_iterator<T, Ref, Ptr>&) { return random_access_iterator_tag(); } template <class T, class Ref, class Ptr> inline T* value_type(const __deque_iterator<T, Ref, Ptr>&) { return 0; } template <class T, class Ref, class Ptr> inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, Ptr>&) { return 0; } #endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */ #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ // See __deque_buf_size(). The only reason that the default value is 0 // is as a workaround for bugs in the way that some compilers handle // constant expressions. // deque 類 template <class T, class Alloc = alloc, size_t BufSiz = 0> class deque { public: // Basic types typedef T value_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; typedef size_t size_type; typedef ptrdiff_t difference_type; public: // Iterators #ifndef __STL_NON_TYPE_TMPL_PARAM_BUG typedef __deque_iterator<T, T&, T*, BufSiz> iterator; typedef __deque_iterator<T, const T&, const T&, BufSiz> const_iterator; #else /* __STL_NON_TYPE_TMPL_PARAM_BUG */ typedef __deque_iterator<T, T&, T*> iterator; typedef __deque_iterator<T, const T&, const T*> const_iterator; #endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */ #ifdef __STL_CLASS_PARTIAL_SPECIALIZATION typedef reverse_iterator<const_iterator> const_reverse_iterator; typedef reverse_iterator<iterator> reverse_iterator; #else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ typedef reverse_iterator<const_iterator, value_type, const_reference, difference_type> const_reverse_iterator; typedef reverse_iterator<iterator, value_type, reference, difference_type> reverse_iterator; #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ protected: // Internal typedefs //元素指針的指針,即指向 map 中元素的指針 typedef pointer* map_pointer; //空間配置器。每次配置一個元素大小 typedef simple_alloc<value_type, Alloc> data_allocator; //空間配置器,每次配置一個指針大小 typedef simple_alloc<pointer, Alloc> map_allocator; static size_type buffer_size() { return __deque_buf_size(BufSiz, sizeof(value_type)); } static size_type initial_map_size() { return 8; } protected: // Data members iterator start; //第一緩沖區的第一個元素 iterator finish; //最後緩沖區的最後一個元素 map_pointer map; //指向 map size_type map_size; // map 內可容納多少指針 public: // Basic accessors iterator begin() { return start; } iterator end() { return finish; } const_iterator begin() const { return start; } const_iterator end() const { return finish; } reverse_iterator rbegin() { return reverse_iterator(finish); } reverse_iterator rend() { return reverse_iterator(start); } const_reverse_iterator rbegin() const { return const_reverse_iterator(finish); } const_reverse_iterator rend() const { return const_reverse_iterator(start); } reference operator[](size_type n) { return start[difference_type(n)]; } const_reference operator[](size_type n) const { return start[difference_type(n)]; } reference front() { return *start; } reference back() { //?

下面三行為什麽不改為: return *(finish - 1); iterator tmp = finish; --tmp; return *tmp; } const_reference front() const { return *start; } const_reference back() const { const_iterator tmp = finish; --tmp; return *tmp; } size_type size() const { return finish - start;; } size_type max_size() const { return size_type(-1); } bool empty() const { return finish == start; } public: // Constructor, destructor. deque() : start(), finish(), map(0), map_size(0) { create_map_and_nodes(0); } deque(const deque& x) : start(), finish(), map(0), map_size(0) { create_map_and_nodes(x.size()); __STL_TRY { uninitialized_copy(x.begin(), x.end(), start); } __STL_UNWIND(destroy_map_and_nodes()); } deque(size_type n, const value_type& value) : start(), finish(), map(0), map_size(0) { fill_initialize(n, value); } deque(int n, const value_type& value) : start(), finish(), map(0), map_size(0) { fill_initialize(n, value); } deque(long n, const value_type& value) : start(), finish(), map(0), map_size(0) { fill_initialize(n, value); } explicit deque(size_type n) : start(), finish(), map(0), map_size(0) { fill_initialize(n, value_type()); } #ifdef __STL_MEMBER_TEMPLATES template <class InputIterator> deque(InputIterator first, InputIterator last) : start(), finish(), map(0), map_size(0) { range_initialize(first, last, iterator_category(first)); } #else /* __STL_MEMBER_TEMPLATES */ deque(const value_type* first, const value_type* last) : start(), finish(), map(0), map_size(0) { create_map_and_nodes(last - first); __STL_TRY { uninitialized_copy(first, last, start); } __STL_UNWIND(destroy_map_and_nodes()); } deque(const_iterator first, const_iterator last) : start(), finish(), map(0), map_size(0) { create_map_and_nodes(last - first); __STL_TRY { uninitialized_copy(first, last, start); } __STL_UNWIND(destroy_map_and_nodes()); } #endif /* __STL_MEMBER_TEMPLATES */ ~deque() { destroy(start, finish); destroy_map_and_nodes(); } deque& operator= (const deque& x) { const size_type len = size(); if (&x != this) { if (len >= x.size()) erase(copy(x.begin(), x.end(), start), finish); else { const_iterator mid = x.begin() + difference_type(len); copy(x.begin(), mid, start); insert(finish, mid, x.end()); } } return *this; } void swap(deque& x) { __STD::swap(start, x.start); __STD::swap(finish, x.finish); __STD::swap(map, x.map); __STD::swap(map_size, x.map_size); } public: // push_* and pop_* void push_back(const value_type& t) { //最後緩沖區尚有一個以上的備用空間 if (finish.cur != finish.last - 1) { construct(finish.cur, t); ++finish.cur; } //僅僅剩一個備用空間 else push_back_aux(t); } void push_front(const value_type& t) { //第一緩沖區尚有備用空間 if (start.cur != start.first) { construct(start.cur - 1, t); --start.cur; } //尚有備用空間 else push_front_aux(t); } void pop_back() { //最後緩沖區有一個或很多其它的元素 if (finish.cur != finish.first) { --finish.cur; //指針前移。相當於排除了最後的元素 destroy(finish.cur); //析構並釋放最後的元素 } //最後緩沖區沒有不論什麽元素 else pop_back_aux(); } void pop_front() { //第一緩沖區有一個或很多其它個元素 if (start.cur != start.last - 1) { destroy(start.cur); ++start.cur; } //第一緩沖區且有一個元素 else pop_front_aux(); } public: // Insert iterator insert(iterator position, const value_type& x) { //假設插入點是 deque 最前端,交給 push_front 去做 if (position.cur == start.cur) { push_front(x); return start; } //假設插入點是 deque 最後端,交給 push_back 去做 else if (position.cur == finish.cur) { push_back(x); iterator tmp = finish; --tmp; return tmp; } //其它情況交給 insert_aux 去做 else { return insert_aux(position, x); } } iterator insert(iterator position) { return insert(position, value_type()); } void insert(iterator pos, size_type n, const value_type& x); void insert(iterator pos, int n, const value_type& x) { insert(pos, (size_type) n, x); } void insert(iterator pos, long n, const value_type& x) { insert(pos, (size_type) n, x); } #ifdef __STL_MEMBER_TEMPLATES template <class InputIterator> void insert(iterator pos, InputIterator first, InputIterator last) { insert(pos, first, last, iterator_category(first)); } #else /* __STL_MEMBER_TEMPLATES */ void insert(iterator pos, const value_type* first, const value_type* last); void insert(iterator pos, const_iterator first, const_iterator last); #endif /* __STL_MEMBER_TEMPLATES */ void resize(size_type new_size, const value_type& x) { const size_type len = size(); if (new_size < len) erase(start + new_size, finish); else insert(finish, new_size - len, x); } void resize(size_type new_size) { resize(new_size, value_type()); } public: // Erase //清除 pos 所指的元素 iterator erase(iterator pos) { iterator next = pos; ++next; difference_type index = pos - start; // 清除點前的元素個數 if (index < (size() >> 1)) { // 假設清除點之前的元素比較少,則移動清除點之前的元素 copy_backward(start, pos, next); pop_front(); } else { //假設清除點之後的元素比較少,則移動清除點之後的元素 copy(next, finish, pos); pop_back(); } return start + index; } iterator erase(iterator first, iterator last); void clear(); protected: // Internal construction/destruction void create_map_and_nodes(size_type num_elements); void destroy_map_and_nodes(); void fill_initialize(size_type n, const value_type& value); #ifdef __STL_MEMBER_TEMPLATES template <class InputIterator> void range_initialize(InputIterator first, InputIterator last, input_iterator_tag); template <class ForwardIterator> void range_initialize(ForwardIterator first, ForwardIterator last, forward_iterator_tag); #endif /* __STL_MEMBER_TEMPLATES */ protected: // Internal push_* and pop_* void push_back_aux(const value_type& t); void push_front_aux(const value_type& t); void pop_back_aux(); void pop_front_aux(); protected: // Internal insert functions #ifdef __STL_MEMBER_TEMPLATES template <class InputIterator> void insert(iterator pos, InputIterator first, InputIterator last, input_iterator_tag); template <class ForwardIterator> void insert(iterator pos, ForwardIterator first, ForwardIterator last, forward_iterator_tag); #endif /* __STL_MEMBER_TEMPLATES */ iterator insert_aux(iterator pos, const value_type& x); void insert_aux(iterator pos, size_type n, const value_type& x); #ifdef __STL_MEMBER_TEMPLATES template <class ForwardIterator> void insert_aux(iterator pos, ForwardIterator first, ForwardIterator last, size_type n); #else /* __STL_MEMBER_TEMPLATES */ void insert_aux(iterator pos, const value_type* first, const value_type* last, size_type n); void insert_aux(iterator pos, const_iterator first, const_iterator last, size_type n); #endif /* __STL_MEMBER_TEMPLATES */ iterator reserve_elements_at_front(size_type n) { size_type vacancies = start.cur - start.first; if (n > vacancies) new_elements_at_front(n - vacancies); return start - difference_type(n); } iterator reserve_elements_at_back(size_type n) { size_type vacancies = (finish.last - finish.cur) - 1; if (n > vacancies) new_elements_at_back(n - vacancies); return finish + difference_type(n); } void new_elements_at_front(size_type new_elements); void new_elements_at_back(size_type new_elements); void destroy_nodes_at_front(iterator before_start); void destroy_nodes_at_back(iterator after_finish); protected: // Allocation of map and nodes // Makes sure the map has space for new nodes. Does not actually // add the nodes. Can invalidate map pointers. (And consequently, // deque iterators.) void reserve_map_at_back (size_type nodes_to_add = 1) { if (nodes_to_add + 1 > map_size - (finish.node - map)) reallocate_map(nodes_to_add, false); } void reserve_map_at_front (size_type nodes_to_add = 1) { if (nodes_to_add > start.node - map) reallocate_map(nodes_to_add, true); } void reallocate_map(size_type nodes_to_add, bool add_at_front); pointer allocate_node() { return data_allocator::allocate(buffer_size()); } void deallocate_node(pointer n) { data_allocator::deallocate(n, buffer_size()); } #ifdef __STL_NON_TYPE_TMPL_PARAM_BUG public: bool operator==(const deque<T, Alloc, 0>& x) const { return size() == x.size() && equal(begin(), end(), x.begin()); } bool operator!=(const deque<T, Alloc, 0>& x) const { return size() != x.size() || !equal(begin(), end(), x.begin()); } bool operator<(const deque<T, Alloc, 0>& x) const { return lexicographical_compare(begin(), end(), x.begin(), x.end()); } #endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */ }; // Non-inline member functions template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::insert(iterator pos, size_type n, const value_type& x) { if (pos.cur == start.cur) { iterator new_start = reserve_elements_at_front(n); uninitialized_fill(new_start, start, x); start = new_start; } else if (pos.cur == finish.cur) { iterator new_finish = reserve_elements_at_back(n); uninitialized_fill(finish, new_finish, x); finish = new_finish; } else insert_aux(pos, n, x); } #ifndef __STL_MEMBER_TEMPLATES template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::insert(iterator pos, const value_type* first, const value_type* last) { size_type n = last - first; if (pos.cur == start.cur) { iterator new_start = reserve_elements_at_front(n); __STL_TRY { uninitialized_copy(first, last, new_start); start = new_start; } __STL_UNWIND(destroy_nodes_at_front(new_start)); } else if (pos.cur == finish.cur) { iterator new_finish = reserve_elements_at_back(n); __STL_TRY { uninitialized_copy(first, last, finish); finish = new_finish; } __STL_UNWIND(destroy_nodes_at_back(new_finish)); } else insert_aux(pos, first, last, n); } template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::insert(iterator pos, const_iterator first, const_iterator last) { size_type n = last - first; if (pos.cur == start.cur) { iterator new_start = reserve_elements_at_front(n); __STL_TRY { uninitialized_copy(first, last, new_start); start = new_start; } __STL_UNWIND(destroy_nodes_at_front(new_start)); } else if (pos.cur == finish.cur) { iterator new_finish = reserve_elements_at_back(n); __STL_TRY { uninitialized_copy(first, last, finish); finish = new_finish; } __STL_UNWIND(destroy_nodes_at_back(new_finish)); } else insert_aux(pos, first, last, n); } #endif /* __STL_MEMBER_TEMPLATES */ template <class T, class Alloc, size_t BufSize> deque<T, Alloc, BufSize>::iterator //清除[first, last)區間內的全部元素 deque<T, Alloc, BufSize>::erase(iterator first, iterator last) { //假設清除區間就是整個 deque ,直接調用 clear() 就可以 if (first == start && last == finish) { clear(); return finish; } else { difference_type n = last - first; difference_type elems_before = first - start; //假設清除區間前面的元素較少,向後移動前方元素(覆蓋清除區間)。然後析構冗余元素 if (elems_before < (size() - n) / 2) { copy_backward(start, first, last); iterator new_start = start + n; destroy(start, new_start); for (map_pointer cur = start.node; cur < new_start.node; ++cur) data_allocator::deallocate(*cur, buffer_size()); start = new_start; } //假設清除區間後面的元素較少。向前移動後方元素,然後析構冗余元素 else { copy(last, finish, first); iterator new_finish = finish - n; destroy(new_finish, finish); for (map_pointer cur = new_finish.node + 1; cur <= finish.node; ++cur) data_allocator::deallocate(*cur, buffer_size()); finish = new_finish; } return start + elems_before; } } //清除整個 deque ,須要保有一個緩沖區。

template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::clear() { //針對頭尾以外的每一個緩沖區。析構全部元素並釋放緩沖區空間 for (map_pointer node = start.node + 1; node < finish.node; ++node) { destroy(*node, *node + buffer_size()); data_allocator::deallocate(*node, buffer_size()); } //還剩頭尾兩個緩沖區 if (start.node != finish.node) { destroy(start.cur, start.last); destroy(finish.first, finish.cur); //僅僅釋放尾部緩沖區的空間,保留頭緩沖區 data_allocator::deallocate(finish.first, buffer_size()); } //僅僅剩一個緩沖區 else //不釋放唯一的緩沖區空間 destroy(start.cur, finish.cur); finish = start; } //產生並安排好 deque 的結構 template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::create_map_and_nodes(size_type num_elements) { //須要的節點數 = (元素個數/每一個緩沖區可容納的元素個數) + 1 //假設剛好整除。會多配一個節點 size_type num_nodes = num_elements / buffer_size() + 1; // initial_map_size 函數返回 8 ,所以這裏是取 8 和 "所需節點數加2(前後預留一個。擴充時可用)" 的最大值 map_size = max(initial_map_size(), num_nodes + 2); //配置出一個"具有 map_size 個節點"的 map map = map_allocator::allocate(map_size); //令 nstart 和 nfinish 指向 map 所擁有之全部節點的最中央區段 map_pointer nstart = map + (map_size - num_nodes) / 2; map_pointer nfinish = nstart + num_nodes - 1; map_pointer cur; __STL_TRY { //為 map 內的每一個現用節點配置緩沖區。

全部緩沖區加起來就是 deque 的可用空間(最後一個緩沖區可能留有一些余裕) for (cur = nstart; cur <= nfinish; ++cur) *cur = allocate_node(); } # ifdef __STL_USE_EXCEPTIONS catch(...) { for (map_pointer n = nstart; n < cur; ++n) deallocate_node(*n); map_allocator::deallocate(map, map_size); throw; } # endif /* __STL_USE_EXCEPTIONS */ //為 deque 內的兩個叠代器 start 和 end 設定正確內容 start.set_node(nstart); finish.set_node(nfinish); start.cur = start.first; finish.cur = finish.first + num_elements % buffer_size(); } // This is only used as a cleanup function in catch clauses. template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::destroy_map_and_nodes() { for (map_pointer cur = start.node; cur <= finish.node; ++cur) deallocate_node(*cur); map_allocator::deallocate(map, map_size); } //負責產生並安排好 deque 的結構,並元素的初值設定妥當 template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::fill_initialize(size_type n, const value_type& value) { create_map_and_nodes(n);//把 deque 的結構都產生並安排好 map_pointer cur; __STL_TRY { //為每一個節點的緩沖區設定初值 for (cur = start.node; cur < finish.node; ++cur) uninitialized_fill(*cur, *cur + buffer_size(), value); //最後一個節點的設定稍有不同(由於尾端可能有備用空間。不必設初值) uninitialized_fill(finish.first, finish.cur, value); } # ifdef __STL_USE_EXCEPTIONS catch(...) { for (map_pointer n = start.node; n < cur; ++n) destroy(*n, *n + buffer_size()); destroy_map_and_nodes(); throw; } # endif /* __STL_USE_EXCEPTIONS */ } #ifdef __STL_MEMBER_TEMPLATES template <class T, class Alloc, size_t BufSize> template <class InputIterator> void deque<T, Alloc, BufSize>::range_initialize(InputIterator first, InputIterator last, input_iterator_tag) { create_map_and_nodes(0); for ( ; first != last; ++first) push_back(*first); } template <class T, class Alloc, size_t BufSize> template <class ForwardIterator> void deque<T, Alloc, BufSize>::range_initialize(ForwardIterator first, ForwardIterator last, forward_iterator_tag) { size_type n = 0; distance(first, last, n); create_map_and_nodes(n); __STL_TRY { uninitialized_copy(first, last, start); } __STL_UNWIND(destroy_map_and_nodes()); } #endif /* __STL_MEMBER_TEMPLATES */ // 僅僅有當 finish.cur == finish.last - 1 時才會調用,即僅僅剩一個備用空間 template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::push_back_aux(const value_type& t) { value_type t_copy = t; reserve_map_at_back(); //配置一個新緩沖區 *(finish.node + 1) = allocate_node(); __STL_TRY { construct(finish.cur, t_copy); //設置元素值 finish.set_node(finish.node + 1); //改變 finish, 令其指向新節點 finish.cur = finish.first; //設定 finish 的狀態 } __STL_UNWIND(deallocate_node(*(finish.node + 1))); } // 僅僅有當 start.cur == start.first 才會被調用。即第一個緩沖區尚有備用空間可用了 //--> 為什麽 push_back 的時候是僅僅有一個備用空間時調用。而 push_front 是沒有備用空間時調用 ?? template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::push_front_aux(const value_type& t) { value_type t_copy = t; reserve_map_at_front(); *(start.node - 1) = allocate_node(); __STL_TRY { start.set_node(start.node - 1); start.cur = start.last - 1; construct(start.cur, t_copy); } # ifdef __STL_USE_EXCEPTIONS catch(...) { start.set_node(start.node + 1); start.cur = start.first; deallocate_node(*(start.node - 1)); throw; } # endif /* __STL_USE_EXCEPTIONS */ } // 僅僅有當 finish.cur == finish.first 時才會調用 template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>:: pop_back_aux() { deallocate_node(finish.first); //釋放最後一個緩沖區 finish.set_node(finish.node - 1); //調整 finish 的狀態,使指向上一個緩沖區的最後一個元素 finish.cur = finish.last - 1; destroy(finish.cur); //將該元素析構 } //僅僅有當 start.cur == start.last - 1 時才會調用 template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::pop_front_aux() { destroy(start.cur); //將第一緩沖區的第一個元素析構 deallocate_node(start.first); //釋放第一緩沖區 start.set_node(start.node + 1); //調整 start 的狀態,使指向下一個緩沖區的第一個元素 start.cur = start.first; } #ifdef __STL_MEMBER_TEMPLATES template <class T, class Alloc, size_t BufSize> template <class InputIterator> void deque<T, Alloc, BufSize>::insert(iterator pos, InputIterator first, InputIterator last, input_iterator_tag) { copy(first, last, inserter(*this, pos)); } template <class T, class Alloc, size_t BufSize> template <class ForwardIterator> void deque<T, Alloc, BufSize>::insert(iterator pos, ForwardIterator first, ForwardIterator last, forward_iterator_tag) { size_type n = 0; distance(first, last, n); if (pos.cur == start.cur) { iterator new_start = reserve_elements_at_front(n); __STL_TRY { uninitialized_copy(first, last, new_start); start = new_start; } __STL_UNWIND(destroy_nodes_at_front(new_start)); } else if (pos.cur == finish.cur) { iterator new_finish = reserve_elements_at_back(n); __STL_TRY { uninitialized_copy(first, last, finish); finish = new_finish; } __STL_UNWIND(destroy_nodes_at_back(new_finish)); } else insert_aux(pos, first, last, n); } #endif /* __STL_MEMBER_TEMPLATES */ template <class T, class Alloc, size_t BufSize> typename deque<T, Alloc, BufSize>::iterator deque<T, Alloc, BufSize>::insert_aux(iterator pos, const value_type& x) { difference_type index = pos - start; value_type x_copy = x; //假設插入點之前的元素個數比較少。在最前端增加與第一個元素同值的元素,然後進行元素移動 if (index < size() / 2) { push_front(front()); iterator front1 = start; ++front1; iterator front2 = front1; ++front2; pos = start + index; iterator pos1 = pos; ++pos1; copy(front2, pos1, front1); } //假設插入點之後的元素個數比較少,在最後端增加與最後一個元素同值的元素。然後進行元素移動 else { push_back(back()); iterator back1 = finish; --back1; iterator back2 = back1; --back2; pos = start + index; copy_backward(pos, back2, back1); } //在插入點上設定新值 *pos = x_copy; return pos; } template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::insert_aux(iterator pos, size_type n, const value_type& x) { const difference_type elems_before = pos - start; size_type length = size(); value_type x_copy = x; if (elems_before < length / 2) { iterator new_start = reserve_elements_at_front(n); iterator old_start = start; pos = start + elems_before; __STL_TRY { if (elems_before >= difference_type(n)) { iterator start_n = start + difference_type(n); uninitialized_copy(start, start_n, new_start); start = new_start; copy(start_n, pos, old_start); fill(pos - difference_type(n), pos, x_copy); } else { __uninitialized_copy_fill(start, pos, new_start, start, x_copy); start = new_start; fill(old_start, pos, x_copy); } } __STL_UNWIND(destroy_nodes_at_front(new_start)); } else { iterator new_finish = reserve_elements_at_back(n); iterator old_finish = finish; const difference_type elems_after = difference_type(length) - elems_before; pos = finish - elems_after; __STL_TRY { if (elems_after > difference_type(n)) { iterator finish_n = finish - difference_type(n); uninitialized_copy(finish_n, finish, finish); finish = new_finish; copy_backward(pos, finish_n, old_finish); fill(pos, pos + difference_type(n), x_copy); } else { __uninitialized_fill_copy(finish, pos + difference_type(n), x_copy, pos, finish); finish = new_finish; fill(pos, old_finish, x_copy); } } __STL_UNWIND(destroy_nodes_at_back(new_finish)); } } #ifdef __STL_MEMBER_TEMPLATES template <class T, class Alloc, size_t BufSize> template <class ForwardIterator> void deque<T, Alloc, BufSize>::insert_aux(iterator pos, ForwardIterator first, ForwardIterator last, size_type n) { const difference_type elems_before = pos - start; size_type length = size(); if (elems_before < length / 2) { iterator new_start = reserve_elements_at_front(n); iterator old_start = start; pos = start + elems_before; __STL_TRY { if (elems_before >= difference_type(n)) { iterator start_n = start + difference_type(n); uninitialized_copy(start, start_n, new_start); start = new_start; copy(start_n, pos, old_start); copy(first, last, pos - difference_type(n)); } else { ForwardIterator mid = first; advance(mid, difference_type(n) - elems_before); __uninitialized_copy_copy(start, pos, first, mid, new_start); start = new_start; copy(mid, last, old_start); } } __STL_UNWIND(destroy_nodes_at_front(new_start)); } else { iterator new_finish = reserve_elements_at_back(n); iterator old_finish = finish; const difference_type elems_after = difference_type(length) - elems_before; pos = finish - elems_after; __STL_TRY { if (elems_after > difference_type(n)) { iterator finish_n = finish - difference_type(n); uninitialized_copy(finish_n, finish, finish); finish = new_finish; copy_backward(pos, finish_n, old_finish); copy(first, last, pos); } else { ForwardIterator mid = first; advance(mid, elems_after); __uninitialized_copy_copy(mid, last, pos, finish, finish); finish = new_finish; copy(first, mid, pos); } } __STL_UNWIND(destroy_nodes_at_back(new_finish)); } } #else /* __STL_MEMBER_TEMPLATES */ template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::insert_aux(iterator pos, const value_type* first, const value_type* last, size_type n) { const difference_type elems_before = pos - start; size_type length = size(); if (elems_before < length / 2) { iterator new_start = reserve_elements_at_front(n); iterator old_start = start; pos = start + elems_before; __STL_TRY { if (elems_before >= difference_type(n)) { iterator start_n = start + difference_type(n); uninitialized_copy(start, start_n, new_start); start = new_start; copy(start_n, pos, old_start); copy(first, last, pos - difference_type(n)); } else { const value_type* mid = first + (difference_type(n) - elems_before); __uninitialized_copy_copy(start, pos, first, mid, new_start); start = new_start; copy(mid, last, old_start); } } __STL_UNWIND(destroy_nodes_at_front(new_start)); } else { iterator new_finish = reserve_elements_at_back(n); iterator old_finish = finish; const difference_type elems_after = difference_type(length) - elems_before; pos = finish - elems_after; __STL_TRY { if (elems_after > difference_type(n)) { iterator finish_n = finish - difference_type(n); uninitialized_copy(finish_n, finish, finish); finish = new_finish; copy_backward(pos, finish_n, old_finish); copy(first, last, pos); } else { const value_type* mid = first + elems_after; __uninitialized_copy_copy(mid, last, pos, finish, finish); finish = new_finish; copy(first, mid, pos); } } __STL_UNWIND(destroy_nodes_at_back(new_finish)); } } template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::insert_aux(iterator pos, const_iterator first, const_iterator last, size_type n) { const difference_type elems_before = pos - start; size_type length = size(); if (elems_before < length / 2) { iterator new_start = reserve_elements_at_front(n); iterator old_start = start; pos = start + elems_before; __STL_TRY { if (elems_before >= n) { iterator start_n = start + n; uninitialized_copy(start, start_n, new_start); start = new_start; copy(start_n, pos, old_start); copy(first, last, pos - difference_type(n)); } else { const_iterator mid = first + (n - elems_before); __uninitialized_copy_copy(start, pos, first, mid, new_start); start = new_start; copy(mid, last, old_start); } } __STL_UNWIND(destroy_nodes_at_front(new_start)); } else { iterator new_finish = reserve_elements_at_back(n); iterator old_finish = finish; const difference_type elems_after = length - elems_before; pos = finish - elems_after; __STL_TRY { if (elems_after > n) { iterator finish_n = finish - difference_type(n); uninitialized_copy(finish_n, finish, finish); finish = new_finish; copy_backward(pos, finish_n, old_finish); copy(first, last, pos); } else { const_iterator mid = first + elems_after; __uninitialized_copy_copy(mid, last, pos, finish, finish); finish = new_finish; copy(first, mid, pos); } } __STL_UNWIND(destroy_nodes_at_back(new_finish)); } } #endif /* __STL_MEMBER_TEMPLATES */ template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::new_elements_at_front(size_type new_elements) { size_type new_nodes = (new_elements + buffer_size() - 1) / buffer_size(); reserve_map_at_front(new_nodes); size_type i; __STL_TRY { for (i = 1; i <= new_nodes; ++i) *(start.node - i) = allocate_node(); } # ifdef __STL_USE_EXCEPTIONS catch(...) { for (size_type j = 1; j < i; ++j) deallocate_node(*(start.node - j)); throw; } # endif /* __STL_USE_EXCEPTIONS */ } template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::new_elements_at_back(size_type new_elements) { size_type new_nodes = (new_elements + buffer_size() - 1) / buffer_size(); reserve_map_at_back(new_nodes); size_type i; __STL_TRY { for (i = 1; i <= new_nodes; ++i) *(finish.node + i) = allocate_node(); } # ifdef __STL_USE_EXCEPTIONS catch(...) { for (size_type j = 1; j < i; ++j) deallocate_node(*(finish.node + j)); throw; } # endif /* __STL_USE_EXCEPTIONS */ } template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::destroy_nodes_at_front(iterator before_start) { for (map_pointer n = before_start.node; n < start.node; ++n) deallocate_node(*n); } template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::destroy_nodes_at_back(iterator after_finish) { for (map_pointer n = after_finish.node; n > finish.node; --n) deallocate_node(*n); } //重換一個 map (配置更大的,拷貝原來的,釋放原來的) template <class T, class Alloc, size_t BufSize> void deque<T, Alloc, BufSize>::reallocate_map(size_type nodes_to_add, bool add_at_front) { size_type old_num_nodes = finish.node - start.node + 1;//舊節點數 size_type new_num_nodes = old_num_nodes + nodes_to_add;//新節點數 map_pointer new_nstart; //當前 map 的大小大於新節點數的兩倍的情況 //即當前 map 足夠大,則調整節點區間讓它落在 map 的中間 if (map_size > 2 * new_num_nodes) { new_nstart = map + (map_size - new_num_nodes) / 2 + (add_at_front ? nodes_to_add : 0); if (new_nstart < start.node) copy(start.node, finish.node + 1, new_nstart); else copy_backward(start.node, finish.node + 1, new_nstart + old_num_nodes); } //否則,配置一塊新的空間 else { size_type new_map_size = map_size + max(map_size, nodes_to_add) + 2; //配置一塊新的空間 map_pointer new_map = map_allocator::allocate(new_map_size); new_nstart = new_map + (new_map_size - new_num_nodes) / 2 + (add_at_front ? nodes_to_add : 0); //拷貝原 map copy(start.node, finish.node + 1, new_nstart); //釋放原 map map_allocator::deallocate(map, map_size); //設定新 map 的起始地址和大小 map = new_map; map_size = new_map_size; } //又一次設定叠代器 start 和 finish start.set_node(new_nstart); finish.set_node(new_nstart + old_num_nodes - 1); } // Nonmember functions. #ifndef __STL_NON_TYPE_TMPL_PARAM_BUG template <class T, class Alloc, size_t BufSiz> bool operator==(const deque<T, Alloc, BufSiz>& x, const deque<T, Alloc, BufSiz>& y) { return x.size() == y.size() && equal(x.begin(), x.end(), y.begin()); } template <class T, class Alloc, size_t BufSiz> bool operator<(const deque<T, Alloc, BufSiz>& x, const deque<T, Alloc, BufSiz>& y) { return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } #endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */ #if defined(__STL_FUNCTION_TMPL_PARTIAL_ORDER) && !defined(__STL_NON_TYPE_TMPL_PARAM_BUG) template <class T, class Alloc, size_t BufSiz> inline void swap(deque<T, Alloc, BufSiz>& x, deque<T, Alloc, BufSiz>& y) { x.swap(y); } #endif #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) #pragma reset woff 1174 #endif __STL_END_NAMESPACE #endif /* __SGI_STL_INTERNAL_DEQUE_H */ // Local Variables: // mode:C++ // End:




STL源代碼剖析 容器 stl_deque.h