boost::pool

Boost庫的pool提供了一個內存池分配器,用於管理在一個獨立的、大的分配空間裏的動態內存分配。Boost庫的pool主要適用於快速分配一樣大小的內存塊,尤爲是反覆分配和釋放一樣大小的內存塊的狀況。使用pool內存池主要有如下兩個優勢:c++

  1. 可以有效地管理許多小型對象的分配和釋放工做,避免了本身去管理內存而產生的內存碎片和效率低下問題。程序員

  2. 告別程序內存泄漏的煩惱,pool庫會在內部對內存自動進行管理,避免了程序員一不當心而形成的內存泄漏問題。安全

pool庫主要提供了四種內存池接口,分別是:markdown

  • 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&lt;&gt; 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-&gt;a!=1 || p-&gt;b != 2 || p-&gt;c !=3); 
    p = pl.construct(7, 8, 9); //構造一個對象,能夠傳遞參數 
    assert(p-&gt;a == 7); 
    object_pool&lt;string&gt; pls; //定義一個分配string對象的內存池 
    for (int i = 0; i &lt; 10 ; ++i) //連續分配大量string對象 
    { 
        string *ps = pls.construct("hello object_pool"); 
        cout &lt;&lt; *ps &lt;&lt; endl; 
    } 
} //全部建立的對象在這裏都被正確析構、釋放內存 
  1. 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;

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息