STL源码剖析

STL源码剖析---空间配置器

看过STL空间配置器的源码,总结一下:
      1、STL空间配置器:主要分三个文件实现,stl_construct.h  这里定义了全局函数construct()和destroy(),负责对象的构造和析构。stl_alloc.h文件中定义了一、二两级配置器,彼此合作,配置器名为alloc. stl_uninitialized.h 这里定义了一些全局函数,用来填充(fill)或复制(copy)大块内存数据,他们也都隶属于STL标准规划。
      在stl_alloc.h中定义了两级配置器,主要思想是申请大块内存池,小块内存直接从内存池中申请,当不够用时再申请新的内存池,还有就是大块内存直接申请。当申请空间大于128字节时调用第一级配置器,第一级配置器没有用operator::new和operator::delete来申请空间,而是直接调用malloc/free和realloc,并且实现了类似c++中new-handler的机制。所谓c++ new handler机制是,你可以要求系统在内存配置需求无法被满足时,调用一个指定的函数。换句话说,一旦::operator::new无法完成任务,在丢出std::bad_alloc异常状态之前,会先调用由客端指定的处理例程,该处理例程通常称为new-handler.new-handler解决内存做法有特定的模式。SGI第一级配置器的allocate()和realloc都是在调用malloc和realloc不成功后,改调用oom_malloc()和oom_realloc(),后两者都有内循环,不断调用"内存不足处理例程",期望在某次调用之后,获得足够的内存而圆满完成任务。但如果“内存不足处理例程“并未被客端设定,oom_malloc()和oom_realloc便调用_THROW_BAD_ALLOC, 丢出bad_alloc异常信息,或利用exit(1)硬生生中止程序。
     在stl_alloc.h中定义的第二级配置器中,如果区块够大,超过128字节时,就移交给第一级配置器处理。当区块小于128字节时,则以内存池管理,此法又称为次层配置,每次配置一大块内存,并维护对应的自由链表(free-list)。下次若再有相同大小的内存需求,就直接从free-list中拔出。如果客端释还小额区块,就由配置器回收到free-lists中,另外,配置器除了负责配置,也负责回收。为了管理方便,SGI第二级配置器会主动将任何小额区块的内存需求量上调至8的倍数。并维护16个free-lists,各自管理大小分别为8,16,24,32,40,48,56,64,72,80,88,96,104, 112,120,128 字节的小额区块。当申请小于等于128字节时就会检查对应的free list,如果free-list中有可用的区块,就直接拿来,如果没有,就准备为对应的free-list 重新填充空间。新的空间将取自内存池,缺省取得20个新节点,如果内存池不足(还足以一个以上的节点),就返回的相应的节点数.如果当内存池中连一个节点大小都不够时,就申请新的内存池,大小为2*total_bytes+ROUND_UP(heap_size>>4),totoal_bytes 为申请的空间大小,ROUND_UP调整为8的倍数,heap_size为当前总申请内存池的大小。如果申请该内存池成功就把原来内存池中剩下的空间分配给适当的free-list.万一山穷水尽,整个system heap空间都不够了(以至无法为内存池注入源头活水),malloc()行动失败,就会四处寻找有无"尚有未用区块,且区块足够大 "之free lists.找到了就挖一块交出,找不到就调用第一级配置器。第一级配置器其实也是使用malloc来配置内存。但它有out-of-memory处理机制(类似new-handler机制),或许有机会释放其他的内存拿来此处使用。如果可以就成功,否则发出bad_alloc异常。
      2、STL的默认内存分配器
      隐藏在这些容器后的内存管理工作是通过STL提供的一个默认的allocator实现的。当然,用户也可以定制自己的allocator,只要实现allocator模板所定义的接口方法即可,然后通过将自定义的allocator作为模板参数传递给STL容器,创建一个使用自定义allocator的STL容器对象,如:
    stl::vector<int, UserDefinedAllocator> array;
      大多数情况下,STL默认的allocator就已经足够了。这个allocator是一个由两级分配器构成的内存管理器,当申请的内存大小大于128byte时,就启动第一级分配器通过malloc直接向系统的堆空间分配,如果申请的内存大小小于128byte时,就启动第二级分配器,从一个预先分配好的内存池中取一块内存交付给用户,这个内存池由16个不同大小(8的倍数,8~128byte)的空闲列表组成,allocator会根据申请内存的大小(将这个大小round up成8的倍数)从对应的空闲块列表取表头块给用户。
这种做法有两个优点:
     (1)小对象的快速分配。小对象是从内存池分配的,这个内存池是系统调用一次malloc分配一块足够大的区域给程序备用,当内存池耗尽时再向系统申请一块新的区域,整个过程类似于批发和零售,起先是由allocator向总经商批发一定量的货物,然后零售给用户,与每次都总经商要一个货物再零售给用户的过程相比,显然是快捷了。当然,这里的一个问题时,内存池会带来一些内存的浪费,比如当只需分配一个小对象时,为了这个小对象可能要申请一大块的内存池,但这个浪费还是值得的,况且这种情况在实际应用中也并不多见。
     (2)避免了内存碎片的生成。程序中的小对象的分配极易造成内存碎片,给操作系统的内存管理带来了很大压力,系统中碎片的增多不但会影响内存分配的速度,而且会极大地降低内存的利用率。以内存池组织小对象的内存,从系统的角度看,只是一大块内存池,看不到小对象内存的分配和释放。
实现时,allocator需要维护一个存储16个空闲块列表表头的数组free_list,数组元素i是一个指向块大小为8*(i+1)字节的空闲块列表的表头,一个指向内存池起始地址的指针start_free和一个指向结束地址的指针end_free。空闲块列表节点的结构如下:

[cpp]  view plain  copy
  1. union obj  
  2. {  
  3.     union obj * free_list_link;  
  4.     char client_data[1];  
  5. };  
      这个结构可以看做是从一个内存块中抠出4个字节大小来,当这个内存块空闲时,它存储了下个空闲块,当这个内存块交付给用户时,它存储的时用户的数据。因此,allocator中的空闲块链表可以表示成:
    obj* free_list[16];
      3、分配算法 

[cpp]  view plain  copy
  1. // 算法:allocate  
  2. // 输入:申请内存的大小size  
  3. // 输出:若分配成功,则返回一个内存的地址,否则返回NULL  
  4. {  
  5.     if(size 大于 128)  
  6.         启动第一级分配器直接调用malloc分配所需的内存并返回内存地址;  
  7.     else  
  8.     {  
  9.         将size向上round up成8的倍数并根据大小从free_list中取对应的表头free_list_head  
  10.         if(free_list_head 不为空)  
  11.         {  
  12.             从该列表中取下第一个空闲块并调整free_list,返回free_list_head  
  13.         }  
  14.         else  
  15.         {  
  16.             调用refill算法建立空闲块列表并返回所需的内存地址  
  17.         }  
  18.     }  
  19. }  
  20.   
  21.   
  22. // 算法:refill  
  23. // 输入:内存块的大小size  
  24. // 输出:建立空闲块链表并返回第一个可用的内存地址  
  25. {  
  26.     调用chunk_alloc算法分配若干个大小为size的连续内存区域并返回起始地址chunk和成功分配的块数nobj  
  27.     if(块数为1)  
  28.         直接返回 chunk;  
  29.     else  
  30.     {  
  31.         开始在chunk地址块中建立free_list  
  32.         根据size取free_list中对应的表头元素free_list_head   
  33.         将free_list_head 指向chunk中偏移起始地址为size的地址处,即free_list_head = (obj*)(chunk+size)  
  34.         再将整个chunk中剩下的nobj-1个内存块串联起来构成一个空闲列表  
  35.         返回chunk,即chunk中第一个空闲的内存块  
  36.     }  
  37. }  
  38.   
  39.   
  40. // 算法:chunk_alloc  
  41. // 输入:内存块的大小size,预分配的内存块数nobj(以引用传递)  
  42. // 输出:一块连续的内存区域的地址和该区域内可以容纳的内存块的块数  
  43. {  
  44.     计算总共所需的内存大小total_bytes  
  45.     if(内存池足以分配,即end_free-start_free >= total_bytes)  
  46.     {  
  47.         则更新start_free  
  48.         返回旧的start_free  
  49.     }  
  50.     else if(内存池不够分配nobj个内存块,但至少可以分配一个)  
  51.     {  
  52.         计算可以分配的内存块数并修改nobj  
  53.         更新start_free并返回原来的start_free  
  54.     }  
  55.     else     // 内存池连一个内存块都分配不了  
  56.     {  
  57.         先将内存池的内存块链入到对应的free_list中后  
  58.         调用malloc操作重新分配内存池,大小为2倍的total_bytes为附加量,start_free指向返回的内存地址  
  59.         if(分配不成功)  
  60.         {  
  61.             if(16个空闲列表中尚有空闲块)  
  62.                 尝试将16个空闲列表中空闲块回收到内存池中再调用chunk_alloc(size,nobj)  
  63.             else  
  64.                 调用第一级分配器尝试out of memory机制是否还有用  
  65.         }  
  66.         更新end_free为start_free+total_bytes,heap_size为2倍的total_bytes  
  67.         调用chunk_alloc(size,nobj)  
  68.     }  
  69. }  
  70.   
  71.   
  72. // 算法:deallocate  
  73. // 输入:需要释放的内存块地址p和大小size  
  74. {  
  75.     if(size 大于128字节)  
  76.         直接调用free(p)释放  
  77.     else  
  78.     {  
  79.         将size向上取8的倍数,并据此获取对应的空闲列表表头指针free_list_head  
  80.         调整free_list_head将p链入空闲列表块中  
  81.     }  
  82. }  
假设这样一个场景,free_list[2]已经指向了大小为24字节的空闲块链表,如图1所示,当用户向allocator申请21字节大小的内存块时,allocaotr会首先检查free_list[2]并将free_list[2]所指的内存块分配给用户,然后将表头指向下一个可用的空闲块,如图2所示。注意,当内存块在链表上是,前4个字节是用作指向下一个空闲块,当分配给用户时,它是一块普通的内存区。
STL源码剖析_第1张图片
                        图1 某时刻allocator的状态 
STL源码剖析_第2张图片
                                  图2 分配24字节大小的内存块 
4、小结
STL中的内存分配器实际上是基于空闲列表(free list)的分配策略,最主要的特点是通过组织16个空闲列表,对小对象的分配做了优化。
1)小对象的快速分配和释放。当一次性预先分配好一块固定大小的内存池后,对小于128字节的小块内存分配和释放的操作只是一些基本的指针操作,相比于直接调用malloc/free,开销小。
2)避免内存碎片的产生。零乱的内存碎片不仅会浪费内存空间,而且会给OS的内存管理造成压力。
3)尽可能最大化内存的利用率。当内存池尚有的空闲区域不足以分配所需的大小时,分配算法会将其链入到对应的空闲列表中,然后会尝试从空闲列表中寻找是否有合适大小的区域,
但是,这种内存分配器局限于STL容器中使用,并不适合一个通用的内存分配。因为它要求在释放一个内存块时,必须提供这个内存块的大小,以便确定回收到哪个free list中,而STL容器是知道它所需分配的对象大小的,比如上述:
    stl::vector<int> array;
array是知道它需要分配的对象大小为sizeof(int)。一个通用的内存分配器是不需要知道待释放内存的大小的,类似于free(p)。


STL源码剖析---vector

vector容器概述
      vector的数据安排以及操作方式,与array非常相似。两者的唯一区别在于空间的运用的灵活性。array是静态空间,一旦配置了就不能改变;要换个大(或小)一点的房子,可以,一切琐细都得由客户端自己来:首先配置一块新空间,然后将元素从旧址一一搬往新址,再把原来的空间释还给系统。vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。因此,vector的运用对于内存的合理利用与运用的灵活性有很大的帮助,我们再也不必因为害怕空间不足而一开始要求一个大块头的array了,我们可以安心使用array,吃多少用多少。
      vector的实现技术,关键在于其对大小的控制以及重新配置时的数据移动效率。一旦vector的旧有空间满载,如果客户端每新增一个元素,vector的内部只是扩充一个元素的空间,实为不智。因为所谓扩充空间(不论多大),一如稍早所说,是”配置新空间/数据移动/释还旧空间“的大工程,时间成本很高,应该加入某种未雨绸缪的考虑。稍后我们便可看到SGI vector的空间配置策略了。
      另外,由于vector维护的是一个连续线性空间,所以vector支持随机存取
      注意:vector动态增加大小时,并不是在原空间之后持续新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原大小的两倍另外配置一块较大的空间,然后将原内容拷贝过来,然后才开始在原内容之后构造新元素,并释放原空间。因此,对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了。这是程序员易犯的一个错误,务需小心。
以下是vector定义的源代码摘录:

[cpp]  view plain  copy
  1. #include<iostream>  
  2. using namespace std;  
  3. #include<memory.h>    
  4.   
  5. // alloc是SGI STL的空间配置器  
  6. template <class T, class Alloc = alloc>  
  7. class vector  
  8. {  
  9. public:  
  10.     // vector的嵌套类型定义,typedefs用于提供iterator_traits<I>支持  
  11.     typedef T value_type;  
  12.     typedef value_type* pointer;  
  13.     typedef value_type* iterator;  
  14.     typedef value_type& reference;  
  15.     typedef size_t size_type;  
  16.     typedef ptrdiff_t difference_type;  
  17. protected:  
  18.     // 这个提供STL标准的allocator接口  
  19.     typedef simple_alloc <value_type, Alloc> data_allocator;  
  20.   
  21.     iterator start;               // 表示目前使用空间的头  
  22.     iterator finish;              // 表示目前使用空间的尾  
  23.     iterator end_of_storage;      // 表示实际分配内存空间的尾  
  24.   
  25.     void insert_aux(iterator position, const T& x);  
  26.   
  27.     // 释放分配的内存空间  
  28.     void deallocate()  
  29.     {  
  30.         // 由于使用的是data_allocator进行内存空间的分配,  
  31.         // 所以需要同样使用data_allocator::deallocate()进行释放  
  32.         // 如果直接释放, 对于data_allocator内部使用内存池的版本  
  33.         // 就会发生错误  
  34.         if (start)  
  35.             data_allocator::deallocate(start, end_of_storage - start);  
  36.     }  
  37.   
  38.     void fill_initialize(size_type n, const T& value)  
  39.     {  
  40.         start = allocate_and_fill(n, value);  
  41.         finish = start + n;                         // 设置当前使用内存空间的结束点  
  42.         // 构造阶段, 此实作不多分配内存,  
  43.         // 所以要设置内存空间结束点和, 已经使用的内存空间结束点相同  
  44.         end_of_storage = finish;  
  45.     }  
  46.   
  47. public:  
  48.     // 获取几种迭代器  
  49.     iterator begin() { return start; }  
  50.     iterator end() { return finish; }  
  51.   
  52.     // 返回当前对象个数  
  53.     size_type size() const { return size_type(end() - begin()); }  
  54.     size_type max_size() const { return size_type(-1) / sizeof(T); }  
  55.     // 返回重新分配内存前最多能存储的对象个数  
  56.     size_type capacity() const { return size_type(end_of_storage - begin()); }  
  57.     bool empty() const { return begin() == end(); }  
  58.     reference operator[](size_type n) { return *(begin() + n); }  
  59.   
  60.     // 本实作中默认构造出的vector不分配内存空间  
  61.     vector() : start(0), finish(0), end_of_storage(0) {}  
  62.   
  63.   
  64.     vector(size_type n, const T& value) { fill_initialize(n, value); }  
  65.     vector(int n, const T& value) { fill_initialize(n, value); }  
  66.     vector(long n, const T& value) { fill_initialize(n, value); }  
  67.   
  68.     // 需要对象提供默认构造函数  
  69.     explicit vector(size_type n) { fill_initialize(n, T()); }  
  70.   
  71.     vector(const vector<T, Alloc>& x)  
  72.     {  
  73.         start = allocate_and_copy(x.end() - x.begin(), x.begin(), x.end());  
  74.         finish = start + (x.end() - x.begin());  
  75.         end_of_storage = finish;  
  76.     }  
  77.   
  78.     ~vector()  
  79.     {  
  80.         // 析构对象  
  81.         destroy(start, finish);  
  82.         // 释放内存  
  83.         deallocate();  
  84.     }  
  85.   
  86.     vector<T, Alloc>& operator=(const vector<T, Alloc>& x);  
  87.   
  88.     // 提供访问函数  
  89.     reference front() { return *begin(); }  
  90.     reference back() { return *(end() - 1); }  
  91.   
  92.     ////////////////////////////////////////////////////////////////////////////////  
  93.     // 向容器尾追加一个元素, 可能导致内存重新分配  
  94.     ////////////////////////////////////////////////////////////////////////////////  
  95.     //                          push_back(const T& x)  
  96.     //                                   |  
  97.     //                                   |---------------- 容量已满?  
  98.     //                                   |  
  99.     //               ----------------------------  
  100.     //           No  |                          |  Yes  
  101.     //               |                          |  
  102.     //               ↓                          ↓  
  103.     //      construct(finish, x);       insert_aux(end(), x);  
  104.     //      ++finish;                           |  
  105.     //                                          |------ 内存不足, 重新分配  
  106.     //                                          |       大小为原来的2倍  
  107.     //      new_finish = data_allocator::allocate(len);       <stl_alloc.h>  
  108.     //      uninitialized_copy(start, position, new_start);   <stl_uninitialized.h>  
  109.     //      construct(new_finish, x);                         <stl_construct.h>  
  110.     //      ++new_finish;  
  111.     //      uninitialized_copy(position, finish, new_finish); <stl_uninitialized.h>  
  112.     ////////////////////////////////////////////////////////////////////////////////  
  113.   
  114.     void push_back(const T& x)  
  115.     {  
  116.         // 内存满足条件则直接追加元素, 否则需要重新分配内存空间  
  117.         if (finish != end_of_storage)  
  118.         {  
  119.             construct(finish, x);  
  120.             ++finish;  
  121.         }  
  122.         else  
  123.             insert_aux(end(), x);  
  124.     }  
  125.   
  126.   
  127.     ////////////////////////////////////////////////////////////////////////////////  
  128.     // 在指定位置插入元素  
  129.     ////////////////////////////////////////////////////////////////////////////////  
  130.     //                   insert(iterator position, const T& x)  
  131.     //                                   |  
  132.     //                                   |------------ 容量是否足够 && 是否是end()?  
  133.     //                                   |  
  134.     //               -------------------------------------------  
  135.     //            No |                                         | Yes  
  136.     //               |                                         |  
  137.     //               ↓                                         ↓  
  138.     //    insert_aux(position, x);                  construct(finish, x);  
  139.     //               |                              ++finish;  
  140.     //               |-------- 容量是否够用?  
  141.     //               |  
  142.     //        --------------------------------------------------  
  143.     //    Yes |                                                | No  
  144.     //        |                                                |  
  145.     //        ↓                                                |  
  146.     // construct(finish, *(finish - 1));                       |  
  147.     // ++finish;                                               |  
  148.     // T x_copy = x;                                           |  
  149.     // copy_backward(position, finish - 2, finish - 1);        |  
  150.     // *position = x_copy;                                     |  
  151.     //                                                         ↓  
  152.     // data_allocator::allocate(len);                       <stl_alloc.h>  
  153.     // uninitialized_copy(start, position, new_start);      <stl_uninitialized.h>  
  154.     // construct(new_finish, x);                            <stl_construct.h>  
  155.     // ++new_finish;  
  156.     // uninitialized_copy(position, finish, new_finish);    <stl_uninitialized.h>  
  157.     // destroy(begin(), end());                             <stl_construct.h>  
  158.     // deallocate();  
  159.     ////////////////////////////////////////////////////////////////////////////////  
  160.   
  161.     iterator insert(iterator position, const T& x)  
  162.     {  
  163.         size_type n = position - begin();  
  164.         if (finish != end_of_storage && position == end())  
  165.         {  
  166.             construct(finish, x);  
  167.             ++finish;  
  168.         }  
  169.         else  
  170.             insert_aux(position, x);  
  171.         return begin() + n;  
  172.     }  
  173.   
  174.     iterator insert(iterator position) { return insert(position, T()); }  
  175.   
  176.     void pop_back()  
  177.     {  
  178.         --finish;  
  179.         destroy(finish);  
  180.     }  
  181.   
  182.     iterator erase(iterator position)  
  183.     {  
  184.         if (position + 1 != end())  
  185.             copy(position + 1, finish, position);  
  186.         --finish;  
  187.         destroy(finish);  
  188.         return position;  
  189.     }  
  190.   
  191.   
  192.     iterator erase(iterator first, iterator last)  
  193.     {  
  194.         iterator i = copy(last, finish, first);  
  195.         // 析构掉需要析构的元素  
  196.         destroy(i, finish);  
  197.         finish = finish - (last - first);  
  198.         return first;  
  199.     }  
  200.   
  201.     // 调整size, 但是并不会重新分配内存空间  
  202.     void resize(size_type new_size, const T& x)  
  203.     {  
  204.         if (new_size < size())  
  205.             erase(begin() + new_size, end());  
  206.         else  
  207.             insert(end(), new_size - size(), x);  
  208.     }  
  209.     void resize(size_type new_size) { resize(new_size, T()); }  
  210.   
  211.     void clear() { erase(begin(), end()); }  
  212.   
  213. protected:  
  214.     // 分配空间, 并且复制对象到分配的空间处  
  215.     iterator allocate_and_fill(size_type n, const T& x)  
  216.     {  
  217.         iterator result = data_allocator::allocate(n);  
  218.         uninitialized_fill_n(result, n, x);  
  219.         return result;  
  220.     }  
  221.   
  222.     // 提供插入操作  
  223.     ////////////////////////////////////////////////////////////////////////////////  
  224.     //                 insert_aux(iterator position, const T& x)  
  225.     //                                   |  
  226.     //                                   |---------------- 容量是否足够?  
  227.     //                                   ↓  
  228.     //              -----------------------------------------  
  229.     //        Yes   |                                       | No  
  230.     //              |                                       |  
  231.     //              ↓                                       |  
  232.     // 从opsition开始, 整体向后移动一个位置                     |  
  233.     // construct(finish, *(finish - 1));                    |  
  234.     // ++finish;                                            |  
  235.     // T x_copy = x;                                        |  
  236.     // copy_backward(position, finish - 2, finish - 1);     |  
  237.     // *position = x_copy;                                  |  
  238.     //                                                      ↓  
  239.     //                            data_allocator::allocate(len);  
  240.     //                            uninitialized_copy(start, position, new_start);  
  241.     //                            construct(new_finish, x);  
  242.     //                            ++new_finish;  
  243.     //                            uninitialized_copy(position, finish, new_finish);  
  244.     //                            destroy(begin(), end());  
  245.     //                            deallocate();  
  246.     ////////////////////////////////////////////////////////////////////////////////  
  247.   
  248.     template <class T, class Alloc>  
  249.     void insert_aux(iterator position, const T& x)  
  250.     {  
  251.         if (finish != end_of_storage)    // 还有备用空间  
  252.         {  
  253.             // 在备用空间起始处构造一个元素,并以vector最后一个元素值为其初值  
  254.             construct(finish, *(finish - 1));  
  255.             ++finish;  
  256.             T x_copy = x;  
  257.             copy_backward(position, finish - 2, finish - 1);  
  258.             *position = x_copy;  
  259.         }  
  260.         else   // 已无备用空间  
  261.         {  
  262.             const size_type old_size = size();  
  263.             const size_type len = old_size != 0 ? 2 * old_size : 1;  
  264.             // 以上配置元素:如果大小为0,则配置1(个元素大小)  
  265.             // 如果大小不为0,则配置原来大小的两倍  
  266.             // 前半段用来放置原数据,后半段准备用来放置新数据  
  267.   
  268.             iterator new_start = data_allocator::allocate(len);  // 实际配置  
  269.             iterator new_finish = new_start;  
  270.             // 将内存重新配置  
  271.             try  
  272.             {  
  273.                 // 将原vector的安插点以前的内容拷贝到新vector  
  274.                 new_finish = uninitialized_copy(start, position, new_start);  
  275.                 // 为新元素设定初值 x  
  276.                 construct(new_finish, x);  
  277.                 // 调整水位  
  278.                 ++new_finish;  
  279.                 // 将安插点以后的原内容也拷贝过来  
  280.                 new_finish = uninitialized_copy(position, finish, new_finish);  
  281.             }  
  282.             catch(...)  
  283.             {  
  284.                 // 回滚操作  
  285.                 destroy(new_start, new_finish);  
  286.                 data_allocator::deallocate(new_start, len);  
  287.                 throw;  
  288.             }  
  289.             // 析构并释放原vector  
  290.             destroy(begin(), end());  
  291.             deallocate();  
  292.   
  293.             // 调整迭代器,指向新vector  
  294.             start = new_start;  
  295.             finish = new_finish;  
  296.             end_of_storage = new_start + len;  
  297.         }  
  298.     }  
  299.   
  300.     ////////////////////////////////////////////////////////////////////////////////  
  301.     // 在指定位置插入n个元素  
  302.     ////////////////////////////////////////////////////////////////////////////////  
  303.     //             insert(iterator position, size_type n, const T& x)  
  304.     //                                   |  
  305.     //                                   |---------------- 插入元素个数是否为0?  
  306.     //                                   ↓  
  307.     //              -----------------------------------------  
  308.     //        No    |                                       | Yes  
  309.     //              |                                       |  
  310.     //              |                                       ↓  
  311.     //              |                                    return;  
  312.     //              |----------- 内存是否足够?  
  313.     //              |  
  314.     //      -------------------------------------------------  
  315.     //  Yes |                                               | No  
  316.     //      |                                               |  
  317.     //      |------ (finish - position) > n?                |  
  318.     //      |       分别调整指针                              |  
  319.     //      ↓                                               |  
  320.     //    ----------------------------                      |  
  321.     // No |                          | Yes                  |  
  322.     //    |                          |                      |  
  323.     //    ↓                          ↓                      |  
  324.     // 插入操作, 调整指针           插入操作, 调整指针           |  
  325.     //                                                      ↓  
  326.     //            data_allocator::allocate(len);  
  327.     //            new_finish = uninitialized_copy(start, position, new_start);  
  328.     //            new_finish = uninitialized_fill_n(new_finish, n, x);  
  329.     //            new_finish = uninitialized_copy(position, finish, new_finish);  
  330.     //            destroy(start, finish);  
  331.     //            deallocate();  
  332.     ////////////////////////////////////////////////////////////////////////////////  
  333.   
  334.     template <class T, class Alloc>  
  335.     void insert(iterator position, size_type n, const T& x)  
  336.     {  
  337.         // 如果n为0则不进行任何操作  
  338.         if (n != 0)  
  339.         {  
  340.             if (size_type(end_of_storage - finish) >= n)  
  341.             {      // 剩下的备用空间大于等于“新增元素的个数”  
  342.                 T x_copy = x;  
  343.                 // 以下计算插入点之后的现有元素个数  
  344.                 const size_type elems_after = finish - position;  
  345.                 iterator old_finish = finish;  
  346.                 if (elems_after > n)  
  347.                 {  
  348.                     // 插入点之后的现有元素个数 大于 新增元素个数  
  349.                     uninitialized_copy(finish - n, finish, finish);  
  350.                     finish += n;    // 将vector 尾端标记后移  
  351.                     copy_backward(position, old_finish - n, old_finish);  
  352.                     fill(position, position + n, x_copy); // 从插入点开始填入新值  
  353.                 }  
  354.                 else  
  355.                 {  
  356.                     // 插入点之后的现有元素个数 小于等于 新增元素个数  
  357.                     uninitialized_fill_n(finish, n - elems_after, x_copy);  
  358.                     finish += n - elems_after;  
  359.                     uninitialized_copy(position, old_finish, finish);  
  360.                     finish += elems_after;  
  361.                     fill(position, old_finish, x_copy);  
  362.                 }  
  363.             }  
  364.             else  
  365.             {   // 剩下的备用空间小于“新增元素个数”(那就必须配置额外的内存)  
  366.                 // 首先决定新长度:就长度的两倍 , 或旧长度+新增元素个数  
  367.                 const size_type old_size = size();  
  368.                 const size_type len = old_size + max(old_size, n);  
  369.                 // 以下配置新的vector空间  
  370.                 iterator new_start = data_allocator::allocate(len);  
  371.                 iterator new_finish = new_start;  
  372.                 __STL_TRY  
  373.                 {  
  374.                     // 以下首先将旧的vector的插入点之前的元素复制到新空间  
  375.                     new_finish = uninitialized_copy(start, position, new_start);  
  376.                     // 以下再将新增元素(初值皆为n)填入新空间  
  377.                     new_finish = uninitialized_fill_n(new_finish, n, x);  
  378.                     // 以下再将旧vector的插入点之后的元素复制到新空间  
  379.                     new_finish = uninitialized_copy(position, finish, new_finish);  
  380.                 }  
  381. #         ifdef  __STL_USE_EXCEPTIONS  
  382.                 catch(...)  
  383.                 {  
  384.                     destroy(new_start, new_finish);  
  385.                     data_allocator::deallocate(new_start, len);  
  386.                     throw;  
  387.                 }  
  388. #         endif /* __STL_USE_EXCEPTIONS */  
  389.                 destroy(start, finish);  
  390.                 deallocate();  
  391.                 start = new_start;  
  392.                 finish = new_finish;  
  393.                 end_of_storage = new_start + len;  
  394.             }  
  395.         }  
  396.     }  
  397. };  

STL源码剖析---list

相较于vector的连续线性空间,list就显得复杂许多,它的好处是每次插入或删除一个元素,就配置或释放一个元素空间。因此,list对于空间的运用有绝对的精准,一点也不浪费。而且,对于任何位置的元素插入或元素移除,list永远是常数时间。
      list不仅是一个双向链表,而且还是一个环状双向链表。另外,还有一个重要性质,插入操作和接合操作都不会造成原有的list迭代器失效,这在vector是不成立的。因为vector的插入操作可能造成记忆体重新配置,导致原有的迭代器全部失效。甚至list的元素删除操作(erase),也只有“指向被删除元素”的那个迭代器失效,其他迭代器不受任何影响。
以下是list的节点、迭代器数据结构设计以及list的源码剖析:

[cpp]  view plain  copy
  1. ////////////////////////////////////////////////////////////////////////////////  
  2. // list结点, 提供双向访问能力  
  3. ////////////////////////////////////////////////////////////////////////////////  
  4. //  --------           --------           --------           --------  
  5. //  | next |---------->| next |---------->| next |---------->| next |  
  6. //  --------           --------           --------           --------  
  7. //  | prev |<----------| prev |<----------| prev |<----------| prev |  
  8. //  --------           --------           --------           --------  
  9. //  | data |           | data |           | data |           | data |  
  10. //  --------           --------           --------           --------  
  11. ////////////////////////////////////////////////////////////////////////////////  
  12.   
  13. template <class T>  
  14. struct __list_node  
  15. {  
  16.     typedef void* void_pointer;  
  17.     void_pointer next;  
  18.     void_pointer prev;  
  19.     T data;  
  20. };  
  21.   
  22. // 至于为什么不使用默认参数, 这个是因为有一些编译器不能提供推导能力,  
  23. // 而作者又不想维护两份代码, 故不使用默认参数  
  24. template<class T, class Ref, class Ptr>  
  25. struct __list_iterator  
  26. {  
  27.     typedef __list_iterator<T, T&, T*>             iterator;   // STL标准强制要求  
  28.     typedef __list_iterator<T, Ref, Ptr>           self;  
  29.   
  30.     typedef bidirectional_iterator_tag iterator_category;  
  31.     typedef T value_type;  
  32.     typedef Ptr pointer;  
  33.     typedef Ref reference;  
  34.     typedef __list_node<T>* link_type;  
  35.     typedef size_t size_type;  
  36.     typedef ptrdiff_t difference_type;  
  37.   
  38.     link_type node;   //迭代器内部当然要有一个普通指针,指向list的节点  
  39.   
  40.     __list_iterator(link_type x) : node(x) {}  
  41.     __list_iterator() {}  
  42.     __list_iterator(const iterator& x) : node(x.node) {}  
  43.   
  44.     // 在STL算法中需要迭代器提供支持  
  45.     bool operator==(const self& x) const { return node == x.node; }  
  46.     bool operator!=(const self& x) const { return node != x.node; }  
  47.   
  48.     // 以下对迭代器取值(dereference),取的是节点的数据值  
  49.     reference operator*() const { return (*node).data; }  
  50.   
  51.     // 以下是迭代器的成员存取运算子的标准做法  
  52.     pointer operator->() const { return &(operator*()); }  
  53.   
  54.     // 前缀自加,对迭代器累加1,就是前进一个节点  
  55.     self& operator++()  
  56.     {  
  57.         node = (link_type)((*node).next);  
  58.         return *this;  
  59.     }  
  60.   
  61.     // 后缀自加, 需要先产生自身的一个副本, 然会再对自身操作, 最后返回副本  
  62.     self operator++(int)  
  63.     {  
  64.         self tmp = *this;  
  65.         ++*this;  
  66.         return tmp;  
  67.     }  
  68.   
  69.     // 前缀自减  
  70.     self& operator--()  
  71.     {  
  72.         node = (link_type)((*node).prev);  
  73.         return *this;  
  74.     }  
  75.   
  76.     self operator--(int)  
  77.     {  
  78.         self tmp = *this;  
  79.         --*this;  
  80.         return tmp;  
  81.     }  
  82. };  
  83.   
  84. ////////////////////////////////////////////////////////////////////////////////  
  85. // list不仅是个双向链表, 而且还是一个环状双向链表  
  86. ////////////////////////////////////////////////////////////////////////////////  
  87. //       end()              头结点             begin()  
  88. //         ↓                  ↓                  ↓  
  89. //      --------           --------           --------           --------  
  90. // ---->| next |---------->| next |---------->| next |---------->| next |------  
  91. // |    --------           --------           --------           --------     |  
  92. // |  --| prev |<----------| prev |<----------| prev |<----------| prev |<--| |  
  93. // |  | --------           --------           --------           --------   | |  
  94. // |  | | data |           | data |           | data |           | data |   | |  
  95. // |  | --------           --------           --------           --------   | |  
  96. // |  |                                                                     | |  
  97. // |  | --------           --------           --------           --------   | |  
  98. // ---|-| next |<----------| next |<----------| next |<----------| next |<--|--  
  99. //    | --------           --------           --------           --------   |  
  100. //    ->| prev |---------->| prev |---------->| prev |---------->| prev |----  
  101. //      --------           --------           --------           --------  
  102. //      | data |           | data |           | data |           | data |  
  103. //      --------           --------           --------           --------  
  104. ////////////////////////////////////////////////////////////////////////////////  
  105.   
  106. // 默认allocator为alloc, 其具体使用版本请参照<stl_alloc.h>  
  107. template <class T, class Alloc = alloc>  
  108. class list  
  109. {  
  110. protected:  
  111.     typedef void* void_pointer;  
  112.     typedef __list_node<T> list_node;  
  113.   
  114.     // 专属之空间配置器,每次配置一个节点大小  
  115.     typedef simple_alloc<list_node, Alloc> list_node_allocator;  
  116.   
  117. public:  
  118.     typedef T value_type;  
  119.     typedef value_type* pointer;  
  120.     typedef value_type& reference;  
  121.     typedef list_node* link_type;  
  122.     typedef size_t size_type;  
  123.     typedef ptrdiff_t difference_type;  
  124.   
  125.     typedef __list_iterator<T, T&, T*>             iterator;  
  126.   
  127. protected:  
  128.     link_type node ;     // 只要一个指针,便可表示整个环状双向链表  
  129.     // 分配一个新结点, 注意这里并不进行构造,  
  130.     // 构造交给全局的construct, 见<stl_stl_uninitialized.h>  
  131.     link_type get_node() { return list_node_allocator::allocate(); }  
  132.   
  133.     // 释放指定结点, 不进行析构, 析构交给全局的destroy  
  134.     void put_node(link_type p) { list_node_allocator::deallocate(p); }  
  135.   
  136.     // 产生(配置并构造)一个节点, 首先分配内存, 然后进行构造  
  137.     // 注: commit or rollback  
  138.     link_type create_node(const T& x)  
  139.     {  
  140.         link_type p = get_node();  
  141.         construct(&p->data, x);  
  142.         return p;  
  143.     }  
  144.   
  145.     // 析构结点元素, 并释放内存  
  146.     void destroy_node(link_type p)  
  147.     {  
  148.         destroy(&p->data);  
  149.         put_node(p);  
  150.     }  
  151.   
  152. protected:  
  153.     // 用于空链表的建立  
  154.     void empty_initialize()  
  155.     {  
  156.         node = get_node();   // 配置一个节点空间,令node指向它  
  157.         node->next = node;   // 令node头尾都指向自己,不设元素值  
  158.         node->prev = node;  
  159.     }  
  160.   
  161.   // 创建值为value共n个结点的链表  
  162.   // 注: commit or rollback  
  163.     void fill_initialize(size_type n, const T& value)  
  164.     {  
  165.         empty_initialize();  
  166.         __STL_TRY  
  167.         {  
  168.             // 此处插入操作时间复杂度O(1)  
  169.             insert(begin(), n, value);  
  170.         }  
  171.         __STL_UNWIND(clear(); put_node(node));  
  172.     }  
  173.       
  174.   
  175. public:  
  176.     list() { empty_initialize(); }  
  177.   
  178.     iterator begin() { return (link_type)((*node).next); }  
  179.   
  180.     // 链表成环, 当指所以头节点也就是end  
  181.     iterator end() { return node; }  
  182.   
  183.     // 头结点指向自身说明链表中无元素  
  184.     bool empty() const { return node->next == node; }  
  185.   
  186.     // 使用全局函数distance()进行计算, 时间复杂度O(n)  
  187.     size_type size() const  
  188.     {  
  189.         size_type result = 0;  
  190.         distance(begin(), end(), result);  
  191.         return result;  
  192.     }  
  193.   
  194.     size_type max_size() const { return size_type(-1); }  
  195.     reference front() { return *begin(); }  
  196.     reference back() { return *(--end()); }  
  197.   
  198.     ////////////////////////////////////////////////////////////////////////////////  
  199.     // 在指定位置插入元素  
  200.     ////////////////////////////////////////////////////////////////////////////////  
  201.     //       insert(iterator position, const T& x)  
  202.     //                       ↓  
  203.     //                 create_node(x)  
  204.     //                 p = get_node();-------->list_node_allocator::allocate();  
  205.     //                 construct(&p->data, x);  
  206.     //                       ↓  
  207.     //            tmp->next = position.node;  
  208.     //            tmp->prev = position.node->prev;  
  209.     //            (link_type(position.node->prev))->next = tmp;  
  210.     //            position.node->prev = tmp;  
  211.     ////////////////////////////////////////////////////////////////////////////////  
  212.   
  213.     iterator insert(iterator position, const T& x)  
  214.     {  
  215.         link_type tmp = create_node(x);   // 产生一个节点  
  216.         // 调整双向指针,使tmp插入进去  
  217.         tmp->next = position.node;  
  218.         tmp->prev = position.node->prev;  
  219.         (link_type(position.node->prev))->next = tmp;  
  220.         position.node->prev = tmp;  
  221.         return tmp;  
  222.     }  
  223.   
  224.   // 指定位置插入n个值为x的元素, 详细解析见实现部分  
  225.   void insert(iterator pos, size_type n, const T& x);  
  226.   void insert(iterator pos, int n, const T& x)  
  227.   {  
  228.       insert(pos, (size_type)n, x);  
  229.   }  
  230.   void insert(iterator pos, long n, const T& x)  
  231.   {  
  232.       insert(pos, (size_type)n, x);  
  233.   }  
  234.   
  235.   // 在链表前端插入结点  
  236.   void push_front(const T& x) { insert(begin(), x); }  
  237.   // 在链表最后插入结点  
  238.   void push_back(const T& x) { insert(end(), x); }  
  239.   
  240.   // 移除迭代器position所指节点  
  241.   iterator erase(iterator position)  
  242.   {  
  243.       link_type next_node = link_type(position.node->next);  
  244.       link_type prev_node = link_type(position.node->prev);  
  245.       prev_node->next = next_node;  
  246.       next_node->prev = prev_node;  
  247.       destroy_node(position.node);  
  248.       return iterator(next_node);  
  249.   }  
  250.   
  251.   // 擦除一个区间的结点, 详细解析见实现部分  
  252.   iterator erase(iterator first, iterator last);  
  253.   
  254.   void resize(size_type new_size, const T& x);  
  255.   void resize(size_type new_size) { resize(new_size, T()); }  
  256.   void clear();  
  257.   
  258.   // 删除链表第一个结点  
  259.   void pop_front() { erase(begin()); }  
  260.   // 删除链表最后一个结点  
  261.   void pop_back()  
  262.   {  
  263.       iterator tmp = end();  
  264.       erase(--tmp);  
  265.   }  
  266.   
  267.   list(size_type n, const T& value) { fill_initialize(n, value); }  
  268.   list(int n, const T& value) { fill_initialize(n, value); }  
  269.   list(long n, const T& value) { fill_initialize(n, value); }  
  270.   
  271.   ~list()  
  272.   {  
  273.     // 释放所有结点  // 使用全局函数distance()进行计算, 时间复杂度O(n)  
  274.   size_type size() const  
  275.   {  
  276.     size_type result = 0;  
  277.     distance(begin(), end(), result);  
  278.     return result;  
  279.   }  
  280.   clear();  
  281.   // 释放头结点  
  282.   put_node(node);  
  283.   }  
  284.   
  285.   list<T, Alloc>& operator=(const list<T, Alloc>& x);  
  286.   
  287. protected:  
  288.   
  289.     ////////////////////////////////////////////////////////////////////////////////  
  290.     // 将[first, last)内的所有元素移动到position之前  
  291.     // 如果last == position, 则相当于链表不变化, 不进行操作  
  292.     ////////////////////////////////////////////////////////////////////////////////  
  293.     // 初始状态  
  294.     //                   first                             last  
  295.     //                     ↓                                 ↓  
  296.     //      --------   --------   --------     --------   --------   --------  
  297.     //      | next |-->| next |-->| next |     | next |-->| next |-->| next |  
  298.     //  ... --------   --------   -------- ... --------   --------   -------- ...  
  299.     //      | prev |<--| prev |<--| prev |     | prev |<--| prev |<--| prev |  
  300.     //      --------   --------   --------     --------   --------   --------  
  301.     //  
  302.     //                           position  
  303.     //                               ↓  
  304.     //      --------   --------   --------   --------   --------   --------  
  305.     //      | next |-->| next |-->| next |-->| next |-->| next |-->| next |  
  306.     //  ... --------   --------   --------   --------   --------   -------- ...  
  307.     //      | prev |<--| prev |<--| prev |<--| prev |<--| prev |<--| prev |  
  308.     //      --------   --------   --------   --------   --------   --------  
  309.     //  
  310.     // 操作完成后状态  
  311.     //                           first  
  312.     //                             |  
  313.     //               --------------|--------------------------------------  
  314.     //               | ------------|------------------------------------ |   last  
  315.     //               | |           ↓                                   | |     ↓  
  316.     //      -------- | |        --------   --------     --------       | |  --------   --------  
  317.     //      | next |-- |  ----->| next |-->| next |     | next |-----  | -->| next |-->| next |  
  318.     //  ... --------   |  |     --------   -------- ... --------    |  |    --------   -------- ...  
  319.     //      | prev |<---  |  ---| prev |<--| prev |     | prev |<-- |  -----| prev |<--| prev |  
  320.     //      --------      |  |  --------   --------     --------  | |       --------   --------  
  321.     //                    |  |                                    | |  
  322.     //                    |  ------                               | |  
  323.     //                    ------- |  ------------------------------ |  
  324.     //                          | |  |                              |  
  325.     //                          | |  |  -----------------------------  
  326.     //                          | |  |  |  
  327.     //                          | |  |  |  position  
  328.     //                          | |  |  |     ↓  
  329.     //      --------   -------- | |  |  |  --------   --------   --------   --------  
  330.     //      | next |-->| next |-- |  |  -->| next |-->| next |-->| next |-->| next |  
  331.     //  ... --------   --------   |  |     --------   --------   --------   -------- ...  
  332.     //      | prev |<--| prev |<---  ------| prev |<--| prev |<--| prev |<--| prev |  
  333.     //      --------   --------            --------   --------   --------   --------  
  334.     ////////////////////////////////////////////////////////////////////////////////  
  335.     void transfer(iterator position, iterator first, iterator last)  
  336.     {  
  337.         if (position != last)   // 如果last == position, 则相当于链表不变化, 不进行操作  
  338.         {  
  339.             (*(link_type((*last.node).prev))).next = position.node;  
  340.             (*(link_type((*first.node).prev))).next = last.node;  
  341.             (*(link_type((*position.node).prev))).next = first.node;  
  342.             link_type tmp = link_type((*position.node).prev);  
  343.             (*position.node).prev = (*last.node).prev;  
  344.             (*last.node).prev = (*first.node).prev;  
  345.             (*first.node).prev = tmp;  
  346.         }  
  347.     }  
  348.   
  349. public:  
  350.     // 将链表x移动到position所指位置之前  
  351.     void splice(iterator position, list& x)  
  352.     {  
  353.         if (!x.empty())  
  354.             transfer(position, x.begin(), x.end());  
  355.     }  
  356.   
  357.     // 将链表中i指向的内容移动到position之前  
  358.     void splice(iterator position, list&, iterator i)  
  359.     {  
  360.         iterator j = i;  
  361.         ++j;  
  362.         if (position == i || position == j) return;  
  363.         transfer(position, i, j);  
  364.     }  
  365.   
  366.     // 将[first, last}元素移动到position之前  
  367.     void splice(iterator position, list&, iterator first, iterator last)  
  368.     {  
  369.         if (first != last)  
  370.             transfer(position, first, last);  
  371.     }  
  372.   
  373.     void remove(const T& value);  
  374.     void unique();  
  375.     void merge(list& x);  
  376.     void reverse();  
  377.     void sort();  
  378.   
  379. };  
  380.   
  381. // 销毁所有结点, 将链表置空  
  382. template <class T, class Alloc>  
  383. void list<T, Alloc>::clear()  
  384. {  
  385.   link_type cur = (link_type) node->next;  
  386.   while (cur != node)  
  387.   {  
  388.     link_type tmp = cur;  
  389.     cur = (link_type) cur->next;  
  390.     destroy_node(tmp);  
  391.   }  
  392.   // 恢复node原始状态  
  393.   node->next = node;  
  394.   node->prev = node;  
  395. }  
  396.   
  397. // 链表赋值操作  
  398. // 如果当前容器元素少于x容器, 则析构多余元素,  
  399. // 否则将调用insert插入x中剩余的元素  
  400. template <class T, class Alloc>  
  401. list<T, Alloc>& list<T, Alloc>::operator=(const list<T, Alloc>& x)  
  402. {  
  403.   if (this != &x)  
  404.   {  
  405.     iterator first1 = begin();  
  406.     iterator last1 = end();  
  407.     const_iterator first2 = x.begin();  
  408.     const_iterator last2 = x.end();  
  409.     while (first1 != last1 && first2 != last2) *first1++ = *first2++;  
  410.     if (first2 == last2)  
  411.       erase(first1, last1);  
  412.     else  
  413.       insert(last1, first2, last2);  
  414.   }  
  415.   return *this;  
  416. }  
  417.   
  418.   
  419. // 移除容器内所有的相邻的重复结点  
  420. // 时间复杂度O(n)  
  421. // 用户自定义数据类型需要提供operator ==()重载  
  422. template <class T, class Alloc>  
  423. void list<T, Alloc>::unique()  
  424. {  
  425.   iterator first = begin();  
  426.   iterator last = end();  
  427.   if (first == last) return;  
  428.   iterator next = first;  
  429.   while (++next != last)  
  430.   {  
  431.     if (*first == *next)  
  432.       erase(next);  
  433.     else  
  434.       first = next;  
  435.     next = first;  
  436.   }  
  437. }  
  438.   
  439. // 假设当前容器和x都已序, 保证两容器合并后仍然有序  
  440. template <class T, class Alloc>  
  441. void list<T, Alloc>::merge(list<T, Alloc>& x)  
  442. {  
  443.   iterator first1 = begin();  
  444.   iterator last1 = end();  
  445.   iterator first2 = x.begin();  
  446.   iterator last2 = x.end();  
  447.   
  448.   // 注意:前提是,两个lists都已经递增排序  
  449.   while (first1 != last1 && first2 != last2)  
  450.     if (*first2 < *first1)  
  451.     {  
  452.       iterator next = first2;  
  453.       transfer(first1, first2, ++next);  
  454.       first2 = next;  
  455.     }  
  456.     else  
  457.       ++first1;  
  458.   if (first2 != last2)  
  459.       transfer(last1, first2, last2);  
  460. }  

STL源码剖析---deque

一、deque的中控器
      deque是连续空间(至少逻辑上看来如此),连续线性空间总令我们联想到array或vector。array无法成长,vector虽可成长,却只能向尾端成长,而且其所谓的成长原是个假象,事实上是(1)另觅更大空间;(2)将原数据复制过去;(3)释放原空间三部曲。如果不是vector每次配置新空间时都有留下一些余裕,其成长假象所带来的代价将是相当高昂。
      deque系由一段一段的定量连续空间构成。一旦有必要在deque的前端或尾端增加新空间,便配置一段定量连续空间,串接在整个deque的头端或尾端。deque的最大任务,便是在这些分段的定量连续空间上,维护其整体连续的假象,并提供随机存取的借口。避开了“重新配置、复制、释放”的轮回,代价则是复杂的迭代器架构。
      受到分段连续线性空间的字面影响,我们可能以为deque的实现复杂度和vector相比虽不中亦不远矣,其实不然。主要因为,既是分段连续线性空间,就必须有中央控制,而为了维持整体连续的假象,数据结构的设计及迭代器前进后退等操作都颇为繁琐。deque的实现代码分量远比vector或list都多得多。
      deque采用一块所谓的map(注意,不是STL的map容器)作为主控。这里所谓map是一小块连续空间,其中每个元素(此处称为一个节点,node)都是指针,指向另一段(较大的)连续线性空间,称为缓冲区。缓冲区才是deque的储存空间主体。SGI STL 允许我们指定缓冲区大小,默认值0表示将使用512 bytes 缓冲区。
二、deque的迭代器
      让我们思考一下,deque的迭代器应该具备什么结构,首先,它必须能够指出分段连续空间(亦即缓冲区)在哪里,其次它必须能够判断自己是否已经处于其所在缓冲区的边缘,如果是,一旦前进或后退就必须跳跃至下一个或上一个缓冲区。为了能够正确跳跃,deque必须随时掌握管控中心(map)。所以在迭代器中需要定义:当前元素的指针,当前元素所在缓冲区的起始指针,当前元素所在缓冲区的尾指针,指向map中指向所在缓区地址的指针。
在进行迭代器的移动时,需要考虑跨缓冲区的情况。
重载前加(减),在实现后加(减)时,调用重载的前加(减)。
重载+=,实现+时,直接调用+=,实现-=时,调用+=负数,实现-时,调用-=.
//当需要实现新的功能时,最好使用已经重载好的操作,即方便有安全。。。。
另外,deque在效率上来说是不够vector好的,因此有时候在对deque进行sort的时候,需要先将元素移到vector再进行sort,然后移回来。

构造函数:根据缓冲区设置大小和元素个数,决定map的大小;给map分配空间,根据缓冲区的个数,分配缓冲区,默认指定一个缓冲区;
 设置start和finish迭代器,满足左闭右开的原则。
 push_back:如果空间满足,直接插入;不满足,调用push_back_aux。
 push_back_aux:先调用reverse_map_at_back,若符合某种条件,重换一个map;分配空间。
 reserve_map_at_back:看看map有没有满,满的话,调用reallocate_map。
 reallocate_map:如果前端或后端pop过多,就会导致大量的空闲空间,如果是这种情况,则不用新分配空间,调整一下start的位置即可;
 如果不够,则需要重新申请空间。
 pop:析构元素,如果是最后一块还需要删除空间。
 erase:需要判断,前面的元素少还是后面的元素少,移动较少的部分。
 insert:判断位置,如果为前端或后端直接调用push操作,否则,移动较少的一端。
deque的构造与内存管理:
由于deque的设计思想就是由一块块的缓存区连接起来的,因此它的内存管理会比较复杂。插入的时候要考虑是否要跳转缓存区、是否要新建map节点(和vector一样,其实是重新分配一块空间给map,删除原来空间)、插入后元素是前面元素向前移动还是后面元素向后面移动(谁小移动谁)。而在删除元素的时候,考虑是将前面元素后移覆盖需要移除元素的地方还是后面元素前移覆盖(谁小移动谁)。移动完以后要析构冗余的元素,释放冗余的缓存区。 

三、deque的源码剖析

[cpp]  view plain  copy
  1. //   deque的特性:  
  2. //   对于任何一个迭代器i  
  3. //     i.node是map array中的某元素的地址. i.node的内容是一个指向某个结点的头的指针  
  4. //     i.first == *(i.node)  
  5. //     i.last  == i.first + node_size  
  6. //     i.cur是一个指向[i.first, i.last)之间的指针  
  7. //       注意: 这意味着i.cur永远是一个可以解引用的指针,  
  8. //            即使其是一个指向结尾后元素的迭代器  
  9. //  
  10. //   起点和终点总是非奇异(nonsingular)的迭代器.  
  11. //     注意: 这意味着空deque一定有一个node, 而一个具有N个元素的deque  
  12. //          (N是Buffer Size)一定有有两个nodes  
  13. //  
  14. //   对于除了start.node和finish.node之外的每一个node, 每一个node中的元素  
  15. //   都是一个初始化过的对象. 如果start.node == finish.node,  
  16. //   那么[start.cur, finish.cur)都是未初始化的空间.  
  17. //   否则, [start.cur, start.last)和[finish.first, finish.cur)都是初始化的对象,  
  18. //   而[start.first, start.cur)和[finish.cur, finish.last)是未初始化的空间  
  19. //  
  20. //   [map, map + map_size)是一个合法的非空区间  
  21. //   [start.node, finish.node]是内含在[map, map + map_size)区间的合法区间  
  22. //   一个在[map, map + map_size)区间内的指针指向一个分配过的node,  
  23. //   当且仅当此指针在[start.node, finish.node]区间内  
  24.   
  25. inline size_t __deque_buf_size(size_t n, size_t sz)    
  26. {    
  27.   return n != 0 ? n : (sz < 512 ? size_t(512 / sz) : size_t(1));    
  28. }  
  29.   
  30. // __deque_iterator的数据结构  
  31. template <class T, class Ref, class Ptr, size_t BufSiz>  
  32. struct __deque_iterator  
  33. {  
  34.     typedef __deque_iterator<T, T&, T*>             iterator;  
  35.     typedef __deque_iterator<T, const T&, const T*> const_iterator;  
  36.     static size_t buffer_size() {return __deque_buf_size(0, sizeof(T)); }  
  37.   
  38.     typedef random_access_iterator_tag iterator_category;  
  39.     typedef T value_type;  
  40.     typedef Ptr pointer;  
  41.     typedef Ref reference;  
  42.     typedef size_t size_type;  
  43.     typedef ptrdiff_t difference_type;  
  44.     typedef T** map_pointer;  
  45.   
  46.     typedef __deque_iterator self;  
  47.   
  48.     // 保持与容器的联结  
  49.     T* cur;       // 此迭代器所指之缓冲区中的现行元素  
  50.     T* first;     // 此迭代器所指之缓冲区的头  
  51.     T* last;      // 此迭代器所指之缓冲区的尾(含备用空间)  
  52.     map_pointer node;    // 指向管控中心  
  53.   
  54. ////////////////////////////////////////////////////////////////////////////////  
  55. // 这个是deque内存管理的关键, 其模型如下  
  56. ////////////////////////////////////////////////////////////////////////////////  
  57. //  
  58. //       ---------------------------------------------  
  59. // map-->|   |   |   |   |   |   | ..... |   |   |   |<------------------  
  60. //       ---------------------------------------------                  |  
  61. //             |                                                        |  
  62. //             |                                                        |  
  63. //             |   node                                                 |  
  64. //             |   缓冲区buffer, 这里实际存储元素                          |  
  65. //             |   ---------------------------------------------        |  
  66. //             --->|   |   |   |   |   |   | ..... |   |   | X |        |  
  67. //                 ---------------------------------------------        |  
  68. //                   ↑       ↑                             ↑            |  
  69. //             ------        |                             |            |  
  70. //             |             |                             |            |  
  71. //             |   -----------   ---------------------------            |  
  72. //             ----|-----        |                                      |  
  73. //                 |    |        |                                      |  
  74. //                 |    |        |                                      |  
  75. //                 |    |        |                                      |  
  76. //              ---------------------------                             |  
  77. //              | cur | first | end | map |------------------------------  
  78. //              ---------------------------  
  79. //              迭代器, 其内部维护着一个缓冲区状态  
  80. ////////////////////////////////////////////////////////////////////////////////  
  81.     __deque_iterator(T* x, map_pointer y)  
  82.         : cur(x), first(*y), last(*y + buffer_size()), node(y) {}  
  83.     __deque_iterator() : cur(0), first(0), last(0), node(0) {}  
  84.     __deque_iterator(const iterator& x)  
  85.         : cur(x.cur), first(x.first), last(x.last), node(x.node) {}  
  86.   
  87.     reference operator*() const { return *cur; }  
  88.   
  89.     // 判断两个迭代器间的距离  
  90.     difference_type operator-(const self& x) const  
  91.     {  
  92.         return difference_type(buffer_size()) * (node - x.node - 1) +  
  93.             (cur - first) + (x.last - x.cur);  
  94.     }  
  95.   
  96. ////////////////////////////////////////////////////////////////////////////////  
  97. // 下面重载的这些运算符是让deque从外界看上去维护的是一段连续空间的关键!!!  
  98.   
  99. // 前缀自增  
  100. ////////////////////////////////////////////////////////////////////////////////  
  101. // 如果当前迭代器指向元素是当前缓冲区的最后一个元素,  
  102. // 则将迭代器状态调整为下一个缓冲区的第一个元素  
  103. ////////////////////////////////////////////////////////////////////////////////  
  104. // 不是当前缓冲区最后一个元素  
  105. //  
  106. // 执行前缀自增前的状态  
  107. // first          cur                     end  
  108. // ↓               ↓                       ↓  
  109. // ---------------------------------------------  
  110. // |   |   |   |   |   |   | ..... |   |   | X | <----- 当前缓冲区  
  111. // ---------------------------------------------  
  112. //  
  113. // 执行完成后的状态  
  114. // first              cur                 end  
  115. // ↓                   ↓                   ↓  
  116. // ---------------------------------------------  
  117. // |   |   |   |   |   |   | ..... |   |   | X | <----- 当前缓冲区  
  118. // ---------------------------------------------  
  119. //  
  120. ////////////////////////////////////////////////////////////////////////////////  
  121. // 当前元素为当前缓冲区的最后一个元素  
  122. //  
  123. // 执行前缀自增前的状态  
  124. // first                              cur end  
  125. // ↓                                   ↓   ↓  
  126. // ---------------------------------------------  
  127. // |   |   |   |   |   |   | ..... |   |   | X | <----- 当前缓冲区  
  128. // ---------------------------------------------  
  129. //  
  130. // 执行完成后的状态  
  131. // first                                  end  
  132. // ↓                                       ↓  
  133. // ---------------------------------------------  
  134. // |   |   |   |   |   |   | ..... |   |   | X | <----- 下一缓冲区  
  135. // ---------------------------------------------  
  136. // ↑  
  137. // cur  
  138. //  
  139. ////////////////////////////////////////////////////////////////////////////////  
  140.     self& operator++()  
  141.     {  
  142.         ++cur;    // 切换至下一个元素  
  143.         if (cur == last)    // 如果已达到缓冲区的尾端  
  144.         {  
  145.             set_node(node + 1);    // 就切换至下一节点(亦即缓冲区)  
  146.             cur = first;           // 的第一个元素  
  147.         }  
  148.         return *this;  
  149.     }  
  150.   
  151.     // 后缀自增  
  152.     // 返回当前迭代器的一个副本, 并调用前缀自增运算符实现迭代器自身的自增  
  153.     self operator++(int)  
  154.     {  
  155.         self tmp = *this;  
  156.         ++*this;  
  157.         return tmp;  
  158.     }  
  159.   
  160.     // 前缀自减, 处理方式类似于前缀自增  
  161.     // 如果当前迭代器指向元素是当前缓冲区的第一个元素  
  162.     // 则将迭代器状态调整为前一个缓冲区的最后一个元素  
  163.     self& operator--()  
  164.     {  
  165.         if (cur == first)    // 如果已达到缓冲区的头端  
  166.         {  
  167.             set_node(node - 1);    // 就切换至前一节点(亦即缓冲区)  
  168.             cur = last;            // 的最后一个元素  
  169.         }  
  170.         --cur;  
  171.         return *this;  
  172.     }  
  173.   
  174.     self operator--(int)  
  175.     {  
  176.         self tmp = *this;  
  177.         --*this;  
  178.         return tmp;  
  179.     }  
  180.   
  181. ////////////////////////////////////////////////////////////////////////////////  
  182. // 将迭代器向前移动n个元素, n可以为负  
  183. ////////////////////////////////////////////////////////////////////////////////  
  184. //                     operator+=(difference_type n)  
  185. //                                   ↓  
  186. //                      offset = n + (cur - first)  
  187. //                                   |  
  188. //                                   |---------- offset > 0 ? &&  
  189. //                                   |           移动后是否超出当前缓冲区?  
  190. //               ----------------------------  
  191. //           No  |                          |  Yes  
  192. //               |                          |  
  193. //               ↓                          |---------- offset > 0?  
  194. //           cur += n;                      |  
  195. //                              ----------------------------  
  196. //                          Yes |                          | No  
  197. //                              |                          |  
  198. //                              ↓                          |  
  199. //                   计算要向后移动多少个缓冲区                |  
  200. //                   node_offset =                         |  
  201. //                   offset / difference_type              |  
  202. //                   (buffer_size());                      ↓  
  203. //                              |           计算要向前移动多少个缓冲区  
  204. //                              |           node_offset = -difference_type  
  205. //                              |           ((-offset - 1) / buffer_size()) - 1;  
  206. //                              |                          |  
  207. //                              ----------------------------  
  208. //                                           |  
  209. //                                           |  
  210. //                                           ↓  
  211. //                                       调整缓冲区  
  212. //                              set_node(node + node_offset);  
  213. //                                    计算并调整cur指针  
  214. ////////////////////////////////////////////////////////////////////////////////  
  215.     // 以下实现随机存取。迭代器可以直接跳跃n个距离  
  216.     self& operator+=(difference_type n)  
  217.     {  
  218.         difference_type offset = n + (cur - first);  
  219.         if (offset >= 0 && offset < difference_type(buffer_size()))  
  220.             cur += n;        // 目标位置在同一缓冲区内  
  221.         else  
  222.         {           // 目标位置不在同一缓冲区内  
  223.             difference_type node_offset =  
  224.                 offset > 0 ? offset / difference_type(buffer_size())  
  225.                 : -difference_type((-offset - 1) / buffer_size()) - 1;  
  226.             // 切换至正确的节点(亦即缓冲区)  
  227.             set_node(node + node_offset);  
  228.             // 切换至正确的元素  
  229.             cur = first + (offset - node_offset * difference_type(buffer_size()));  
  230.         }  
  231.         return *this;  
  232.     }  
  233.   
  234.     self operator+(difference_type n) const  
  235.     {  
  236.         self tmp = *this;  
  237.   
  238.         // 这里调用了operator +=()可以自动调整指针状态  
  239.         return tmp += n;  
  240.     }  
  241.   
  242.     // 将n变为-n就可以使用operator +=()了,  
  243.     self& operator-=(difference_type n) { return *this += -n; }  
  244.   
  245.     self operator-(difference_type n) const  
  246.     {  
  247.         self tmp = *this;  
  248.         return tmp -= n;  
  249.     }  
  250.   
  251.     reference operator[](difference_type n) const { return *(*this + n); }  
  252.   
  253.     bool operator==(const self& x) const { return cur == x.cur; }  
  254.     bool operator!=(const self& x) const { return !(*this == x); }  
  255.     bool operator<(const self& x) const  
  256.     {  
  257.         return (node == x.node) ? (cur < x.cur) : (node < x.node);  
  258.     }  
  259.   
  260.     void set_node(map_pointer new_node)  
  261.     {  
  262.         node = new_node;  
  263.         first = *new_node;  
  264.         last = first + difference_type(buffer_size());  
  265.     }  
  266. };  
  267.   
  268.   
  269. // deque的数据结构  
  270. template <class T, class Alloc = alloc, size_t BufSiz = 0>  
  271. class deque  
  272. {  
  273. public:                         // Basic types  
  274.     typedef T value_type;  
  275.     typedef value_type* pointer;  
  276.     typedef value_type& reference;  
  277.     typedef size_t size_type;  
  278.     typedef ptrdiff_t difference_type;  
  279.   
  280. public:                         // Iterators  
  281.     typedef __deque_iterator<T, T&, T*, BufSiz>       iterator;  
  282.   
  283. protected:                      // Internal typedefs  
  284.   
  285.     typedef pointer* map_pointer;  
  286.   
  287.     // 这个提供STL标准的allocator接口, 见<stl_alloc.h>  
  288.     typedef simple_alloc<value_type, Alloc> data_allocator;  
  289.     typedef simple_alloc<pointer, Alloc> map_allocator;  
  290.   
  291.     // 获取缓冲区最大存储元素数量  
  292.     static size_type buffer_size()  
  293.     {  
  294.         return __deque_buf_size(BufSiz, sizeof(value_type));  
  295.     }  
  296.   
  297.     static size_type initial_map_size() { return 8; }  
  298.   
  299. protected:                      // Data members  
  300.     iterator start;               // 起始缓冲区  
  301.     iterator finish;              // 最后一个缓冲区  
  302.   
  303.     // 指向map, map是一个连续的空间, 其每个元素都是一个指针,指向一个节点(缓冲区)  
  304.     map_pointer map;  
  305.     size_type map_size;   // map容量  
  306.   
  307. public:  
  308.     iterator begin() { return start; }  
  309.     iterator end() { return finish; }  
  310.   
  311.     // 提供随机访问能力, 其调用的是迭代器重载的operator []  
  312.     // 其实际地址需要进行一些列的计算, 效率有损失  
  313.     reference operator[](size_type n) { return start[difference_type(n)]; }  
  314.   
  315.     reference front() { return *start; }  
  316.     reference back()  
  317.     {  
  318.         iterator tmp = finish;  
  319.         --tmp;  
  320.         return *tmp;  
  321.     }  
  322.   
  323.     // 当前容器拥有的元素个数, 调用迭代器重载的operator -  
  324.     size_type size() const { return finish - start;; }  
  325.     size_type max_size() const { return size_type(-1); }  
  326.   
  327.     // deque为空的时, 只有一个缓冲区  
  328.     bool empty() const { return finish == start; }  
  329.   
  330. public:                         // Constructor, destructor.  
  331.     deque() : start(), finish(), map(0), map_size(0)  
  332.     {  
  333.         create_map_and_nodes(0);  
  334.     }  
  335.   
  336.     deque(size_type n, const value_type& value)  
  337.         : start(), finish(), map(0), map_size(0)  
  338.     {  
  339.         fill_initialize(n, value);  
  340.     }  
  341.   
  342.     deque(int n, const value_type& value)  
  343.         : start(), finish(), map(0), map_size(0)  
  344.     {  
  345.         fill_initialize(n, value);  
  346.     }  
  347.   
  348.   
  349.     ~deque()  
  350.     {  
  351.         destroy(start, finish);     // <stl_construct.h>  
  352.         destroy_map_and_nodes();  
  353.     }  
  354.   
  355.     deque& operator= (const deque& x)  
  356.     {  
  357.         // 其实我觉得把这个操作放在if内效率更高  
  358.         const size_type len = size();  
  359.         if (&x != this)  
  360.         {  
  361.             // 当前容器比x容器拥有元素多, 析构多余元素  
  362.             if (len >= x.size())  
  363.                 erase(copy(x.begin(), x.end(), start), finish);  
  364.             // 将x所有超出部分的元素使用insert()追加进去  
  365.             else {  
  366.                 const_iterator mid = x.begin() + difference_type(len);  
  367.                 copy(x.begin(), mid, start);  
  368.                 insert(finish, mid, x.end());  
  369.             }  
  370.         }  
  371.         return *this;  
  372.     }  
  373.   
  374. public:  
  375.     void push_back(const value_type& t)  
  376.     {  
  377.         // 最后缓冲区尚有两个(含)以上的元素备用空间  
  378.         if (finish.cur != finish.last - 1)  
  379.         {  
  380.             construct(finish.cur, t);     // 直接在备用空间上构造元素  
  381.             ++finish.cur;     // 调整最后缓冲区的使用状态  
  382.         }  
  383.         // 容量已满就要新申请内存了  
  384.         else  
  385.             push_back_aux(t);  
  386.     }  
  387.   
  388.     void push_front(const value_type& t)  
  389.     {  
  390.         if (start.cur != start.first)      // 第一缓冲区尚有备用空间  
  391.         {  
  392.             construct(start.cur - 1, t);   // 直接在备用空间上构造元素  
  393.             --start.cur;     // 调整第一缓冲区的使用状态  
  394.         }  
  395.         else    // 第一缓冲区已无备用空间  
  396.             push_front_aux(t);  
  397.     }  
  398.   
  399.     void pop_back()  
  400.     {  
  401.         if (finish.cur != finish.first)    // 最后缓冲区有一个(或更多)元素  
  402.         {  
  403.             --finish.cur;    // 调整指针,相当于排除了最后元素  
  404.             destroy(finish.cur);    // 将最后元素析构  
  405.         }  
  406.         else  
  407.             // 最后缓冲区没有任何元素  
  408.             pop_back_aux();    // 这里将进行缓冲区的释放工作  
  409.     }  
  410.   
  411.     void pop_front()  
  412.     {  
  413.         if (start.cur != start.last - 1)    // 第一缓冲区有两个(或更多)元素  
  414.         {  
  415.             destroy(start.cur);    // 将第一元素析构  
  416.             ++start.cur;           //调整指针,相当于排除了第一元素  
  417.         }  
  418.         else  
  419.             // 第一缓冲区仅有一个元素  
  420.             pop_front_aux();    // 这里将进行缓冲区的释放工作  
  421.     }  
  422.   
  423. public:                         // Insert  
  424.   
  425. ////////////////////////////////////////////////////////////////////////////////  
  426. // 在指定位置前插入元素  
  427. ////////////////////////////////////////////////////////////////////////////////  
  428. //             insert(iterator position, const value_type& x)  
  429. //                                   |  
  430. //                                   |---------------- 判断插入位置  
  431. //                                   |  
  432. //               -----------------------------------------------  
  433. // deque.begin() |          deque.emd() |                      |  
  434. //               |                      |                      |  
  435. //               ↓                      ↓                      |  
  436. //         push_front(x);         push_back(x);                |  
  437. //                                                             ↓  
  438. //                                                 insert_aux(position, x);  
  439. //                                                 具体剖析见后面实现  
  440. ////////////////////////////////////////////////////////////////////////////////  
  441.   
  442.     iterator insert(iterator position, const value_type& x)  
  443.     {  
  444.         // 如果是在deque的最前端插入, 那么直接push_front()即可  
  445.         if (position.cur == start.cur)  
  446.         {  
  447.             push_front(x);  
  448.             return start;  
  449.         }  
  450.         // 如果是在deque的末尾插入, 直接调用push_back()  
  451.         else if (position.cur == finish.cur)  
  452.         {  
  453.             push_back(x);  
  454.             iterator tmp = finish;  
  455.             --tmp;  
  456.             return tmp;  
  457.         }  
  458.         else  
  459.         {  
  460.             return insert_aux(position, x);  
  461.         }  
  462.     }  
  463.   
  464.     iterator insert(iterator position) { return insert(position, value_type()); }  
  465.   
  466.     // 详解见实现部分  
  467.     void insert(iterator pos, size_type n, const value_type& x);  
  468.   
  469.     void insert(iterator pos, int n, const value_type& x)  
  470.     {  
  471.         insert(pos, (size_type) n, x);  
  472.     }  
  473.     void insert(iterator pos, long n, const value_type& x)  
  474.     {  
  475.         insert(pos, (size_type) n, x);  
  476.     }  
  477.   
  478.     void resize(size_type new_size) { resize(new_size, value_type()); }  
  479.   
  480. public:                         // Erase  
  481.   
  482.     iterator erase(iterator pos)  
  483.     {  
  484.         iterator next = pos;  
  485.         ++next;  
  486.   
  487.         // 清除点之前的元素个数  
  488.         difference_type index = pos - start;  
  489.   
  490.         // 如果清除点之前的元素个数比较少, 哪部分少就移动哪部分  
  491.         if (index < (size() >> 1))  
  492.         {  
  493.             // 就移动清除点之前的元素  
  494.             copy_backward(start, pos, next);  
  495.             pop_front();   // 移动完毕,最前一个元素冗余,去除之  
  496.         }  
  497.         else   // 如果清除点之后的元素个数比较少  
  498.         {  
  499.             copy(next, finish, pos);  // 就移动清除点之后的元素  
  500.             pop_back();   // 移动完毕,最后一个元素冗余,去除之  
  501.         }  
  502.         return start + index;  
  503.     }  
  504.   
  505.     iterator erase(iterator first, iterator last);  
  506.     void clear();  
  507.   
  508. protected:  
  509.   
  510.     // 详解见实现部分  
  511.     void push_back_aux(const value_type& t);  
  512.     void push_front_aux(const value_type& t);  
  513.     void pop_back_aux();  
  514.     void pop_front_aux();  
  515.   
  516.     iterator insert_aux(iterator pos, const value_type& x);  
  517.     void insert_aux(iterator pos, size_type n, const value_type& x);  
  518.   
  519.     // 分配内存, 不进行构造  
  520.     pointer allocate_node() { return data_allocator::allocate(buffer_size()); }  
  521.   
  522.     // 释放内存, 不进行析构  
  523.     void deallocate_node(pointer n)  
  524.     {  
  525.         data_allocator::deallocate(n, buffer_size());  
  526.     }  
  527.   
  528. };  
  529.   
  530.   
  531. ////////////////////////////////////////////////////////////////////////////////  
  532. // 清除[first, last)区间的所有元素  
  533. ////////////////////////////////////////////////////////////////////////////////  
  534. //                  erase(iterator first, iterator last)  
  535. //                                   |  
  536. //                                   |---------------- 是否要删除整个区间?  
  537. //                                   |  
  538. //               ------------------------------------------  
  539. //           Yes |                                        | No  
  540. //               |                                        |  
  541. //               ↓                                        | --- 判断哪侧元素少  
  542. //            clear();                                    ↓  
  543. //       -----------------------------------------------------------------  
  544. // 左侧少 |                                                         右侧少 |  
  545. //       |                                                               |  
  546. //       ↓                                                               ↓  
  547. //   copy_backward(start, first, last);            copy(last, finish, first);  
  548. //   new_start = start + n;                        new_finish = finish - n;  
  549. //   析构多余的元素                                  析构多余的元素  
  550. //   destroy(start, new_start);                    destroy(new_finish, finish);  
  551. //   释放多余内存空间                                释放多余内存空间  
  552. //   for (...)                                     for (...)  
  553. //      ...                                             ...  
  554. //   更新map状态                                    更新map状态  
  555. ////////////////////////////////////////////////////////////////////////////////  
  556. template <class T, class Alloc, size_t BufSize>  
  557. deque<T, Alloc, BufSize>::iterator  
  558. deque<T, Alloc, BufSize>::erase(iterator first, iterator last)  
  559. {  
  560.     if (first == start && last == finish)   // 如果清除区间是整个deque  
  561.     {  
  562.         clear();              // 直接调用clear()即可  
  563.         return finish;  
  564.     }  
  565.     else  
  566.     {  
  567.         difference_type n = last - first;   // 清除区间的长度  
  568.         difference_type elems_before = first - start;   // 清除区间前方的元素个数  
  569.         if (elems_before < (size() - n) / 2)   // 如果前方的元素个数比较少  
  570.         {  
  571.             copy_backward(start, first, last);  // 向后移动前方元素(覆盖清除区间)  
  572.             iterator new_start = start + n;     // 标记deque的新起点  
  573.             destroy(start, new_start);          // 移动完毕,将冗余的元素析构  
  574.             // 以下将冗余的缓冲区释放  
  575.             for (map_pointer cur = start.node; cur < new_start.node; ++cur)  
  576.                 data_allocator::deallocate(*cur, buffer_size());  
  577.             start = new_start;   // 设定deque的新起点  
  578.         }  
  579.         else    // 如果清除区间后方的元素个数比较少  
  580.         {  
  581.             copy(last, finish, first);  // 向前移动后方元素(覆盖清除区间)  
  582.             iterator new_finish = finish - n;     // 标记deque的新尾点  
  583.             destroy(new_finish, finish);          // 移动完毕,将冗余的元素析构  
  584.             // 以下将冗余的缓冲区释放  
  585.             for (map_pointer cur = new_finish.node + 1; cur <= finish.node; ++cur)  
  586.                 data_allocator::deallocate(*cur, buffer_size());  
  587.             finish = new_finish;   // 设定deque的新尾点  
  588.         }  
  589.         return start + elems_before;  
  590.     }  
  591. }  
  592.   
  593. template <class T, class Alloc, size_t BufSize>  
  594. void deque<T, Alloc, BufSize>::clear()  
  595. {  
  596.     // 以下针对头尾以外的每一个缓冲区  
  597.     for (map_pointer node = start.node + 1; node < finish.node; ++node)  
  598.     {  
  599.         // 将缓冲区内的所有元素析构  
  600.         destroy(*node, *node + buffer_size());  
  601.         // 释放缓冲区内存  
  602.         data_allocator::deallocate(*node, buffer_size());  
  603.     }  
  604.   
  605.     if (start.node != finish.node)   // 至少有头尾两个缓冲区  
  606.     {  
  607.         destroy(start.cur, start.last);  // 将头缓冲区的目前所有元素析构  
  608.         destroy(finish.first, finish.cur);  // 将尾缓冲区的目前所有元素析构  

你可能感兴趣的:(数据结构,C++,源码,算法,C++11)