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;

相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息