STL定義了兩種空間配置器:
- allocator:位于<defalloc.h>
- alloc:在<memory>包含以下頭文件,將功能分離:
-
- 全局函數construct()/destroy():位于<stl_construct.h>,用于構造/析構對象。
- 配置器alloc:位于<stl_alloc.h>,用于空間配置,分為一級配置器和二級配置器。
- uninitialized_copy/uninitialized_fill/uninitialized_fill_n:位于<stl_uninitialized.h>,用于填充或復制大塊數據。
allocator配置器在分配空間時使用標準庫函數operator new/operator delete。處于效率考慮,STL沒有使用這個allocator,而是使用了更為精細的alloc配置器,將空間管理和對象管理兩個階段分離開來。
這樣是為了解決內存碎片問題,TSL的空間配置器分兩級。當申請空間大于128bytes時,使用第一級配置器;當申請空間小于128bytes時,使用第二級配置器。
- 第一級:__malloc_alloc_template,直接使用malloc、realloc、free管理內存。
- 第二級:__default_alloc_template,采用memory pool,由free-list維護。總共有16個free-list,每個free-list串聯了一個個的內存塊,當申請內存時就從一個適當的free-list中拔出一個區塊給用戶,用完后在返還給free-list。
兩個空間配置器都是通過標準接口allocate()、deallocate()進入空間分配和空間釋放的過程的。
無論alloc被定義為第一級或第二級配置器,SGI還為它再包裝一個接口simple_alloc,每一個容器都直接包含這個類,當需要配置空間時,再由此類轉調用allocate或deallocate:
~~~
template<class T, class Alloc>
class simple_alloc { // 對配置器alloc再進行一次封裝,容器就使用這個類進行空間管理
public:
static T *allocate(size_t n)
{ return 0 == n? 0 : (T*) Alloc::allocate(n * sizeof (T)); }
static T *allocate(void)
{ return (T*) Alloc::allocate(sizeof (T)); }
static void deallocate(T *p, size_t n)
{ if (0 != n) Alloc::deallocate(p, n * sizeof (T)); }
static void deallocate(T *p)
{ Alloc::deallocate(p, sizeof (T)); }
};
~~~
容器內部直接使用這個類分配空間,例如在vector中:
~~~
typedef T value_type;
typedef simple_alloc<value_type, Alloc> data_allocator;
~~~
注意只是定義了空間分配器的類型,并沒有定義實際對象。
當要分配或刪除節點時:
~~~
iterator new_start = data_allocator::allocate(len); // 分配元素空間
data_allocator::deallocate(new_start, len); // 刪除元素空間
~~~
利用類型限定符進行空間分配和釋放。
參考:
《STL源碼剖析》第二章。
- 前言
- 順序容器 — heap
- 關聯容器 — 紅黑樹
- 關聯容器 — set
- 關聯容器 — map
- 關聯容器 — hashtable
- 關聯容器 — hash_set
- 關聯容器 — hash_map
- 算法 — copy
- 順序容器 — stack
- 順序容器 — queue
- 順序容器 — priority_queue
- 順序容器 — slist
- construct()和destroy()
- 空間配置器
- 函數適配器
- 迭代器以及“特性萃取機”iterator_traits
- 算法 — partial_sort
- 算法 — sort
- 仿函數
- 適配器(adapters)
- C++簡易vector
- C++簡易list
- STL算法實現
- C++模板Queue