zoukankan      html  css  js  c++  java
  • STL源代码剖析 容器 stl_deque.h

    本文为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:




  • 相关阅读:
    内存泄漏 Memory Leaks 内存优化 MD
    Handler Thread 内部类引起内存泄露分析
    为什么不取消注册BroadcastReceiver会导致内存泄漏
    WebChromeClient 简介 API 案例
    WebViewClient 简介 API 案例
    java.net.URI 简介 文档 API
    android.net.Uri 简介 API
    RV 多样式 MultiType 聊天界面 消息类型 MD
    JS函数声明与定义,作用域,函数声明与表达式的区别
    CSS中table tr:nth-child(even)改变tr背景颜色: IE7,8无效
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/7216874.html
Copyright © 2011-2022 走看看