條款11 理解自定義分配器的正確用法

2021-04-08 14:53:32 字數 2369 閱讀 9278

你用了基準測試,效能剖析,而且實驗了你的方法得到預設的stl記憶體管理器(即allocator )在你的stl需求中太慢、浪費記憶體或造成過度的碎片的結論,並且你肯定你自己能做得比它好。或者你發現allocator對執行緒安全採取了措拖,但是你只對單執行緒的程式感興趣,你不想花費你不需要的同步開銷。或者你知道在某些容器裡的物件通常一同被使用,所以你想在乙個特別的堆裡把它們放得很近使引用的區域性最大化。或者你想建立乙個相當共享記憶體的唯一的堆,然後把乙個或多個容器放在那塊記憶體裡,因為這樣它們可以被其他程序共享。 恭喜你!這些情況正好對應於一種適合於自定義分配器解決的方案。

例如,假定你有仿效malloc和free的特別程式,用於管理共享記憶體的堆,

void* mallocshared(size_t bytesneeded);

void freeshared(void *ptr);

並且你希望能把stl容器的內容放在共享記憶體中。沒問題:

templateclass sharedmemoryanocator

void deallocate(pointer ptrtomemory, size_ type numobjects)

...

};allocate裡的pointer型別、對映和乘法的更多資訊參見條款10。

你可以像這樣使用sharedmemoryallocator:

// 方便的typedef

typedef vector>

shareddoublevec;

...在緊挨著v定義的注釋裡的詞語很重要。v使用sharedmemoryallocator,所以v分配來容納它元素的記憶體將來自共享記憶體,但v本身——包括它的全部資料成員——幾乎將肯定不被放在共享記憶體裡,v只是乙個普通的基於堆的物件,所以它將被放在執行時系統為所有普通的基於堆的物件使用的任何記憶體。那幾乎不會是共享記憶體。為了把v的內容和v本身放進共享記憶體,你必須做像這樣的事情:

void *pvectormemory = // 分配足夠的共享記憶體

mallocshared(sizeof(shareddoublevec)); // 來容納乙個

// shareddoublevec物件

shareddoublevec *pv = // 使用「placement new」來

new (pvectormemory) shareddoublevec; // 在那塊記憶體中建立

// 乙個shareddoublevec物件;

// 參見下面

// 這個物件的使用(通過pv)

...pv->~shareddoublevec(); // 銷毀共享記憶體

// 中的物件

freeshared(pvectormemory); // 銷毀原來的

// 共享記憶體塊

我希望那些注釋讓你清楚是怎麼工作的。基本上,你獲得一些共享記憶體,然後在裡面建立乙個用共享記憶體為自己內部分配的vector。當你用完這個vector時,你呼叫它的析構函式,然後釋放vector占用的記憶體。**不很複雜,但我們在上面所做的比僅僅宣告乙個本地變數要苛刻得多。除非你真的要讓乙個容器(與它的元素相反)在共享記憶體裡,否則我希望你能避免這個手工的四步分配/建造/銷毀/**的過程。

作為分配器作用的第二個例子,假設你有兩個堆,命名為heap1和heap2類。每個堆類有用於進行分配和**的靜態成員函式:

class heap1 ;

class heap2 ; // 有相同的alloc/dealloc介面

更進一步認為你想在不同的堆裡聯合定位一些stl容器的內容。同樣沒有問題。首先,你設計乙個分配器,使用像heap1和heap2那樣用於真實記憶體管理的類:

templateclass specificheapallocator

void deallocate(pointer ptrtomemory, size_type numobjects)

...

};然後你使用specificheapallocator來把容器的元素集合在一起:

vector> v; // 把v和s的元素

set> s; // 放進heap1

list> l; // 把l和m的元素

map, // 放進heap2

specificheapallocator,

heap2> > m;

在這個例子裡,很重要的一點是heap1和heap2是型別而不是物件。stl為用不同的分配器物件初始化相同型別的不同stl容器提供了語法,但是我將不讓你看它是什麼。那是因為如果heap1和heap2是物件而不是型別,那麼它們將是不等價的分配器,那就違反了分配器的等價約束,在條款10有詳細說明。

因為這些例子演示的,分配器在許多情況裡有用。只要你遵循相同型別的所有分配器都一定等價的限制條件,你將毫不費力地使用自定義分配器來控制一般記憶體管理策略,群集關係和使用共享記憶體以及其他特殊的堆。

自定義事件的理解

cc.eventmanager.dispatchcustomevent throw this 丟擲乙個自定義事件,throw用於接收方辨別接收的是哪個事件this.listener cc.eventmanager.addcustomlistener throw this.chek.bind this...

條目十一《理解自定義分配子的合理用法》

根據大牛們的測試 stl預設的記憶體管理器 allocator 太慢,或者浪費記憶體,或者在使用的時候會產生記憶體碎片。又或者需求不一樣時 1.allocator是多執行緒安全的,而你執行環境是單執行緒,所以想減少執行緒同步帶來的te不必要開銷。2.當想把容器的物件放到乙個特殊堆的相鄰位置,做到引用...

關於flex自定義事件的理解

你可以這樣理解事件類 1.第一步,首先忘記你學到的任何關於事件類的知識,不知道有這麼一回事,然後只知道flash有個內建類,名叫event 2.第二步,來看這個類有什麼 它有很多很多常數屬性,比如complete,close,clear等等。那麼,這些引數幹什麼用的呢?很明確的告訴你,flash已經...