STL空間配置器的union obj

2021-08-07 10:31:28 字數 1853 閱讀 9549

最近學習《stl原始碼剖析》一書,看到sgi的第二級配置器時,空閒記憶體鍊錶使用了乙個神奇的聯合體(union)結構,**如下:

[cpp]view plain

copy

union

obj;  

書中描述為這樣:由於union之故,從其第一欄位觀之,obj可被視為乙個指標,指向相同形式的另乙個obj。從其第二欄位觀之,obj可被視為乙個指標,指向實際區塊。union的特性就是其記憶體空間為其成員中最長長度的整數倍,而且可作為成員中的任意一種型別來使用,他們共用同一塊記憶體空間。該聯合體第乙個欄位是指向下乙個union obj的指標,按32位位址空間算,其長度應該為4byte。第二個欄位是長度為1的乙個陣列,也就是1byte;看到這裡我就無法理解了,長度為一的陣列有什麼意義呢?看看下面的栗子:

[cpp]view plain

copy

char

client_data;    

/*此處的client_data是乙個char型變數*/

char

client_data[1]; 

/*而此處client_data是乙個陣列的首位址*/

他們的區別如上所示,這樣就好理解了,事實上我們所關注的並不是client_data[1]裡面的內容,而是client_data這個陣列首位址。由於client_data[1]和free_list_link使用的是同一塊記憶體區域,因此他們的記憶體布局應該如下所示:

由於free_list_link長度較大,union obj的長度為它的整數倍,client_data[1]只佔了其頭部的乙個位元組。因此client_data首位址指向的也就是整個union obj的首位址,亦即實際區塊的位址。再看看下面乙個栗子:

[cpp]view plain

copy

// 下面這段**中的兩個輸出值完全一樣

obj * block = (obj *) malloc(128);  

printf("%x\n"

, block);  

printf("%x\n"

, block->client_data);  

// 然後再將它串接到free_list中去

block->free_list_link = free_list;  

free_list = block;  

// 使用時將其取出,指向下乙個區塊的free_list_link此時就被我們當做空閒區域來使用了,因而不會額外占用空間

obj *myblock = free_list;  

free_list = free_list->free_list_link;  

// 之後直接使用myblock->client_data來訪問該記憶體區域

// ..............

// ..............

試驗我們會發現client_data和myblock的位址完全相同,那麼問題來了:既然它們值是一樣的,作者為什麼還要畫蛇添足的為obj增加client_data這個成員呢?我比較同意的一種觀點是:這裡client_data其實是作為一種指標型別轉換,為了方便使用。一般記憶體buffer我們都是使用char*指標,如果要使用obj的位址,還得加上 (char *)myblock 進行強制型別轉換。反之直接使用myblock->client_data即可,方便多了。

STL 空間配置器

stl有6大元件 容器 演算法 迭代器 仿函式 配接器 分配器。它們之間的密切關係是stl的精髓所在,容器用來存放資料,而容器存在的前提是要有分配器給它分配記憶體,接下來需要實現演算法,迭代器便作為演算法來對容器資料操作的橋梁,演算法可以使用仿函式完成不同的策略變化,配接器可修飾或套接仿函式。說了麼...

STL 空間配置器

stl空間配置器的底層原理 維護了乙個狹義的記憶體池,並且用乙個自由鍊錶來維護該記憶體池。該自由鍊錶比較類似於雜湊的開鏈法的儲存結構。源 pragma once using namespace std define throw bad alloc cerr out of memory endl ex...

STL空間配置器

一級空間配置器 ifndef malloc alloc template h define malloc alloc template h if 0 include define throw bad alloc throw bad alloc elif defined throw bad alloc...