空間配置器的標準介面(根據
stl規範)
allocator::value_type
allocator::pointer
allocator::const_pointer
allocator::reference
allocator::const_reference
allocator::size_type
allocator::difference_type
allocator::rebind //
乙個巢狀的類模板
allocator::allocator()
allocator::allocator(const allocator&)
templateallocator::allocator(const allocator&)
//泛化的拷貝建構函式
allocator::~allocator()
pointer allocator::
address
(reference x) const
//返回某個物件的位址
. a.address(x)
等於&x
const_pointer allocator::address(const_reference x) const
//同上
. 返回乙個
const
物件的位址
pointer allocator::
allocate
(size_type n, const void* = 0 )
//分配空間
, 足以儲存n個
t物件void allocator::
deallocate
(pointer p, size_type n)
//釋放空間
size_type allocator::
max_size
() const
//返回可成功分配的最大量
void allocator::
construct
(pointer p , const t& x)
//負責構造
相當於new ((const void*)p) t(x)
void allocator::
destroy
(pointer p)
//負責析構
相當於p->~t()
——————————————————————————————————————
sgi stl
的配置器與眾不同,
名稱是alloc
而不是allocator
,而且不接受任何引數。
vector> iv; //in vc or cb
vectoriv; //in gcc
但是通常都是使用預設的空間配置器,而
sgi stl
已經為每乙個容器都指定了預設的空間配置器。所以使用的時候無太大區別。
template
class vector; //
預設使用
alloc
————————————————————————————————————————
sgi空間配置器分析:
c++的
new操作符和
delete
操作符進行記憶體配置時,
new:先配置記憶體,然後構造物件。
delete
:先析構物件,然後釋放記憶體。
sgi stl
將記憶體配置、釋放記憶體與構造、析構分開。前者由
中的allocate()
和deallocate()
負責,後者由
中的construct()
和destroy()
負責。這兩個標頭檔案包含於
中(stl
標準規定,配置器定義在
memory
中)。同時
還包含了乙個檔案
,定義了一些全域性函式用來填充、複製大塊記憶體資料。 1.
構造和析構。
構造:template
inline void construct(t1 *p, const t2& value)
template
__destroy_aux(forwarditerator first, forwarditerator last, __ture_type) {}
同時這個析構函式對
char*
和wchar_t*
有特化版本:將不呼叫他們的析構函式。(這是沒有必要呼叫析構函式的例子麼?)
2. 空間的配置和釋放:
std::alloc
std::alloc
為了效率,設計了雙層級配置器,第一級直接使用c的
malloc()
和free()
。第二級則視配置區塊的大小選擇配置器,如果區塊大,則直接呼叫第一級,如果區塊過小,則採用
memory pool
整理的方法。
sgi將其簡單的包裝了乙個介面,
******_alloc
類。使其符合
stl規格。而在使用的時候全部使用的
******_alloc
介面(預設使用)。
第一級配置器: 呼叫
malloc()
和realloc()
,如果配置不成功,則呼叫
oom_malloc(), oom_realloc()(ps
:oom= out of memory
)。在oom_***
的處理時,通過不斷呼叫
「記憶體不足處理例程
」,期望在某次呼叫之後能夠分配到。設計
「記憶體不足處理例程
」是客戶端的責任。(
effective c++
對new-handler
的行為有乙個條款,還沒認真看)
第二級配置器:
由於太多小額的區塊會造成記憶體的碎片,同時也會帶來額外的負擔,因此通過第二級配置器的分配,適當的將小額記憶體分配出去。當區塊小(
<128bytes
)的時候,採用記憶體池管理。第二級配置器維護了16個
free-lists
,各自管理從
8~128bytes
的小額區塊,每乙個區塊以
8bytes
遞增(將每乙個小額的區塊需求上調至
8的倍數,以便管理)。每一次需要時候就將適當的記憶體從
free-lists
中間拔出來。客戶釋放後就**到
free-lists
中。當需要的
free-lists
中沒有可用的區塊的時候,呼叫
refill()
函式為free-lists
填充新的空間(取自記憶體池,用
chunk_alloc()
函式)。記憶體池的處理十分複雜,看的一頭霧水。
sgi配置器使用方法:
template
class vector;
其中第二個
template
引數接受預設的
alloc
,可以是第一級配置器也可以是第二級配置器。
sgi stl
已經把它設定為第二級配置器。
3. 記憶體基本處理工具
在標頭檔案
中,定義了
3個全域性函式,
uninitialized_copy(),uninitialized_fill(),uninitialized_fill_n().
看到這些名字應該就知道它們是什麼作用了,它們負責在已分配好的空間進行構造。這三個函式都具有
」commit or rollback」
語意。要麼構造出所有元素,要麼不構造任何東西。
在具體的實現中,這三個函式也用到了
traits
技法,通過
traits
萃取出元素的特性,如果是
pod(
plain old data
)型別,說明其擁有
trivial ctor/ dtor/ copy/ assignment
函式,因此可以使用
copy()
、fill()
、fill_n()
等演算法,如果不是
pod型別就只能夠迴圈呼叫
construct()
函式了。這裡用到的也是函式過載的方法,和上面
destroy
用到的方法是一樣的。
注意:在
unitialized_copy()
實現的時候,針對
char*
和wchar_t*
兩種型別,可以採用最有效率的
memmove()
來複製,因此需要兩份特化版本。
SGI STL空間配置器和記憶體池
最近在看侯捷老師的 stl原始碼剖析 非常感嘆其中空間配置器實現的巧妙和細緻,對效率真正是錙銖必較。一般我們所習慣的記憶體配置和釋放是通過new和delete來完成的,而new運算包含了兩個階段 1.呼叫 operator new配置記憶體 2.呼叫建構函式 foo 構造物件。delete運算也包含...
STL 空間配置器
stl有6大元件 容器 演算法 迭代器 仿函式 配接器 分配器。它們之間的密切關係是stl的精髓所在,容器用來存放資料,而容器存在的前提是要有分配器給它分配記憶體,接下來需要實現演算法,迭代器便作為演算法來對容器資料操作的橋梁,演算法可以使用仿函式完成不同的策略變化,配接器可修飾或套接仿函式。說了麼...
STL 空間配置器
stl空間配置器的底層原理 維護了乙個狹義的記憶體池,並且用乙個自由鍊錶來維護該記憶體池。該自由鍊錶比較類似於雜湊的開鏈法的儲存結構。源 pragma once using namespace std define throw bad alloc cerr out of memory endl ex...