BOOST内存管理(二) --- boost::pool
?Boost庫的pool提供了一個內存池分配器,用于管理在一個獨立的、大的分配空間里的動態內存分配。Boost庫的pool主要適用于快速分配同樣大小的內存塊,尤其是反復分配和釋放同樣大小的內存塊的情況。使用pool內存池主要有以下兩個優點:
1.?能夠有效地管理許多小型對象的分配和釋放工作,避免了自己去管理內存而產生的內存碎片和效率低下問題。
2.??告別程序內存泄漏的煩惱,pool庫會在內部對內存自動進行管理,避免了程序員一不小心而造成的內存泄漏問題。
????? pool庫主要提供了四種內存池接口,分別是pool、object_pool、singleton_pool和pool_allocator(fast_pool_allocator)。
?
1. ? pool
pool是最簡單也最容易使用的內存池類,可以返回一個簡單數據類型(POD) 的內存指針。它
pool很容易使用,可以像C中的malloc()一樣分配內存,然后隨意使用。除非有特殊要求,否則不必對分配的內存調用free()釋放,pool會很好地管理內存。例如:
#include <boost/pool/pool.hpp> using namespace boost; int main() { pool<> pl(sizeof(int)); //一個可分配int的內存池 int *p = (int *)pl.malloc(); //必須把void*轉換成需要的類型 assert(pl.is_from(p)); pl.free(p); //釋放內存池分配的內存塊 for (int i = 0;i < 100; ++i) //連續分配大量的內存 { pl.ordered_malloc(10); } }2. ?object_pool
object_pool是用于類實例(對象)的內存池,它的功能與pool類似,但會在析構時對所有已經分配的內存塊調用析構函數,從而正確地釋放資源。
malloc()和free()函數分別分配和釋放一塊類型為ElementType*的內存塊,同樣,可以用is_from()來測試內存塊的歸屬,只有是本內存池分配的內存才能被free()釋放。但它們被調用時并不調用類的構造函數和析構函數,也就是說操作的是一塊原始內存塊,里面的值是未定義的,因此我們應當盡量少使用malloc()和free()。
object_pool的特殊之處是construct()和destroy()函數,這兩個函數是object_ pool的真正價值所在。construct()實際上是一組函數,有多個參數的重載形式(目前最多支持3個參數,但可以擴展),它先調用malloc()分配內存,然后再在內存塊上使用傳入的參數調用類的構造函數,返回的是一個已經初始化的對象指針。destory()則先調用對象的析構函數,然后再用free()釋放內存塊。
這些函數都不會拋出異常,如果內存分配失敗,將返回0。
object_pool的用法也是很簡單,我們既可以像pool那樣分配原始內存塊,也可以使用construct()來直接在內存池中創建對象。當然,后一種使用方法是最方便的,也是本書所推薦的。
下面的代碼示范了object_pool的用法:
#include <boost/pool/object_pool.hpp> using namespace boost; struct demo_class //一個示范用的類 { public: int a,b,c; demo_class(int x = 1, int y = 2, int z = 3):a(x),b(y),c(z){} }; int main() { object_pool<demo_class> pl; //對象內存池 demo_class *p = pl.malloc(); //分配一個原始內存塊 assert(pl.is_from(p)); //p指向的內存未經過初始化 assert(p->a!=1 || p->b != 2 || p->c !=3); p = pl.construct(7, 8, 9); //構造一個對象,可以傳遞參數 assert(p->a == 7); object_pool<string> pls; //定義一個分配string對象的內存池 for (int i = 0; i < 10 ; ++i) //連續分配大量string對象 { string *ps = pls.construct("hello object_pool"); cout << *ps << endl; } }
3. ? singleton_pool
singleton_pool與pool的接口完全一致,可以分配簡單數據類型(POD)的內存指針,但它是一個單件,并提供線程安全。
singleton_pool主要有兩個模板類型參數(其余的可以使用缺省值)。第一個Tag僅僅是用于標記不同的單件,可以是空類,甚至是聲明(這個用法還被用于boost.exception,參見4.9小節,136頁)。第二個參數RequestedSize等同于pool構造函數中的整數requested_ size,指示pool分配內存塊的大小。
singleton_pool的接口與pool完全一致,但成員函數均是靜態的,因此不需要聲明singleton_pool的實例 ,直接用域操作符::來調用靜態成員函數。因為singleton_pool是單件,所以它的生命周期與整個程序同樣長,除非手動調用release_memory()或purge_memory(),否則singleton_pool不會自動釋放所占用的內存。除了這兩點,singleton_pool的用法與pool完全相同。
下面的代碼示范了singleton_pool的用法:
#include <boost/pool/singleton_pool.hpp> using namespace boost; struct pool_tag{}; //僅僅用于標記的空類 typedef singleton_pool<pool_tag, sizeof(int)> spl; //內存池定義 int main() { int *p = (int *)spl::malloc(); //分配一個整數內存塊 assert(spl::is_from(p)); spl::release_memory(); //釋放所有未被分配的內存 }singleton_pool在使用時最好使用typedef來簡化名稱,否則會使得類型名過于冗長而難以使用。如代碼中所示:
typedef singleton_pool<pool_tag, sizeof(int)> spl;用于標記的類pool_tag可以再進行簡化,直接在模板參數列表中聲明tag類,這樣可以在一條語句中完成對singleton_pool的類型定義,例如:
typedef singleton_pool<struct pool_tag, sizeof(int)> spl;pool_allocator接口:頭文件<boost/pool/pool_alloctor.hpp>,主要與STL的容器一起使用,可用于代替STL中的allocator.示例代碼如下:
vector<int,pool_allocator<int>> vctTemp; list<char , fast_pool_allocator<char>> listTemp;其中,pool_allocator的內部實現調用了ordered_malloc和ordered_free,可以滿足對大連的連續內存塊的分配請求.fast_pool_allocator的內部實現調用了malloc和freee,比較適合于一次請求單個大內存塊的情況,但也使用與通用分配,不過具有一些性能上的缺點.
總結
以上是生活随笔為你收集整理的BOOST内存管理(二) --- boost::pool的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BOOST内存管理(一) --- boo
- 下一篇: C++虚继承(一) --- vtordi