Boost庫的pool提供了一個內存池分配器,用於管理在一個獨立的、大的分配空間裏的動態內存分配。Boost庫的pool主要適用於快速分配一樣大小的內存塊,尤爲是反覆分配和釋放一樣大小的內存塊的狀況。使用pool內存池主要有如下兩個優勢:c++
1. 可以有效地管理許多小型對象的分配和釋放工做,避免了本身去管理內存而產生的內存碎片和效率低下問題。程序員
2. 告別程序內存泄漏的煩惱,pool庫會在內部對內存自動進行管理,避免了程序員一不當心而形成的內存泄漏問題。安全
pool庫主要提供了四種內存池接口,分別是:markdown
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);
}
}
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;
}
} //全部建立的對象在這裏都被正確析構、釋放內存
singleton_poolui
singleton_pool與pool的接口徹底一致,能夠分配簡單數據類型(POD)的內存指針,但它是一個單件,並提供線程安全。spa
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(); //釋放全部未被分配的內存 } //spl的內存直到程序結束才完
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;