STL源码剖析 容器 stl_deque.h

来源:互联网 发布:查莉娅伤害数据 编辑:程序博客网 时间:2024/05/02 04:58

本文为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,返回 1inline 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_BUGtemplate <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_BUGtemplate <class T, class Ref, class Ptr, size_t BufSiz>inline random_access_iterator_tagiterator_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_tagiterator_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_BUGpublic:  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 functionstemplate <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>::iteratordeque<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);    //拷贝原 mapcopy(start.node, finish.node + 1, new_nstart);    //释放原 mapmap_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_BUGtemplate <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:



0 0
原创粉丝点击