内存管理之内存池(boost) 内存管理之内存池1. pool 库概述boost.pool 库基于简单分隔存储的思想实现了一个快速、紧凑的内存池库不仅能够管理大量的对象还可以用作 STL 的内存分配器。在某种程度上讲它类似一个小型的垃圾回收机制在需要大量分配/释放小对象时其效率很高而且完全不需要考虑delete。2. poolpool是最简单、最容易使用的内存池类其可以返回一个简单数据类型的内存指针。其需要包含的头文件如下boost/pool/pool.hpp。2.1 类摘要pool的类摘要如下templatetypenameUserAllocatordefault_user_allocator_new_deleteclasspool{public:// 构造函数和析构函数explicitpool(size_type requested_size);~pool();// 分配内存块的大小size_typeget_requested_size()const;// 分配内存void*malloc();void*ordered_malloc();void*ordered_malloc(size_type n);boolis_from(void*chunk)const;// 归还内存voidfree(void*chunk);voidordered_free(void*chunk);voidfree(void*chunk,size_type n);voidordered_free(void*chunk,size_type n);// 释放内存boolrelease_memory();boolpurge_memory();};2.2 操作函数pool的模板类型参数UserAllocator是一个用户定义的内存分配器它实现了特定的内存分配算法通常可以直接用默认的default_user_allocator_new_delete它使用new[]和delete[]分配内存。pool的构造函数可以接收一个size_type类型的整数requested_size指示每次分配内存块的大小这个值可以通过get_requested_size()获得。pool会根据需要自动地向系统申请或归还使用的内存在析构时pool将自动释放它所持有的所有内存。成员函数malloc()和ordered_malloc()的行为类似 C 中的全局函数malloc()。malloc()从内存池中任意分配一个内存块而ordered_malloc()则在分配的同时合并空闲块链表。ordered_malloc()带参数的形式可以连续分配 n 块内存。可以使用is_from()函数测试分配后的内存块是否从这个内存池分配出去的。free()用于手动释放之前分配的内存块这些内存块必须是从这个内存池分配出去的。release_memory()让内存池释放所有未被分配的内存但已分配的内存块不受影响purge_memory()则强制释放pool持有的所有内存。2.3 用法代码示例#includeiostream#includeboost/pool/pool.hpp// pool.cppintmain(){boost::poolpl(sizeof(int));// 一个可分配 int 的内存池// 必须把 void* 转换成需要的类型int*pstatic_castint*(pl.malloc());// 判断是否分配成功if(p!nullptr){// 判断 p 是否来自于 plif(pl.is_from(p)){std::cout内存块 p 来自 plstd::endl;}}// 释放内存池分配的内存块pl.free(p);// 连续分配大量的内存for(inti0;i100;i){pl.ordered_malloc(10);}return0;}编译运行# 编译g-opool_demo pool.cpp# 运行./pool_demopool只能作为普通类型如 int、double 等的内存池不能将其应用于复杂的类和对象因为它只分配内存不调用构造函数。调用构造函数时我们需要使用object_poll。3. object_poolobject_pool是用于类实例对象的内存池它的功能与pool类似但会在析构时对所有已分配的内存块调用析构函数。其包含在头文件boost/pool/object_pool.hpp。3.1 类摘要obejct_pool的类摘要如下templatetypenameT,typenameUserAllocatorclassobject_pool:protectedpoolUserAllocator{public:typedefT element_type;object_pool();~object_pool();// 分配内存和归还内存element_type*malloc();voidfree(element_type*p);boolis_from(element_type*p)const;// 创建对象 和 销毁对象element_type*construct(...);voiddestory(element_type*p);};3.2 操作函数object_pool是pool的子类但它使用的是保护继承因此不能使用pool的接口。object_pool的特殊之处是construct()和destory()函数。construct()实际上是一组函数有多个参数的重载形式其先调用malloc分配内存再在内存块上使用传入的参数调用类的构造函数返回的是一个已经初始化的对象指针。destroy()则先调用对象的析构函数再用free释放内存块。这些函数都不会抛出异常如果内存分配失败将返回 0空指针3.3 用法我们可以像pool那样使用object_pool分配原始内存块也可以使用construct()直接在内存池中创建对象。代码示例#includeiostream#includeboost/pool/object_pool.hpp// object_pool.cpp// 示范用的类structdemo_class{public:inta,b,c;demo_class(intx1,inty2,intz3):a(x),b(y),c(z){}};intmain(){// 对象内存池boost::object_pooldemo_classpl;autoppl.malloc();assert(pl.is_from(p));// p 指向的内存未经过初始化assert(p-a!1||p-b!2||p-c!3);// construct 构造对象可以传递参数ppl.construct(7,8,9);std::coutp-a p-b p-cstd::endl;// 定义一个分配 string 对象的内存池boost::object_poolstd::stringpls;// 连续分配大量 string 对象for(inti0;i10;i){std::string*pspls.construct(hello object_pool);std::cout*psstd::endl;}return0;}编译运行# 编译g-oobject_pool_demo object_pool.cpp# 运行./object_pool_demo4. singleton_poolsingleton_pool与pool的接口完全一致可以用它分配简单数据类型POD的内存指针但它是一个“单件”。“单件”指的是单例模式singelton_pool不需要创建对象其把所有的接口都变成了静态函数整个程序全局只有一个内存池实例。singleton_pool默认使用 boost.thread 库提供线程安全保证所以需要将它链接 boost_thread 库如果不使用多线程那么可以在头文件前定义宏BOOST_POOL_NO_MT。4.1 类摘要singleton_pool的类摘要如下所示templatetypenameTag,unsignedRequestedSizeclasssingleton_pool{public:staticboolis_from(void*ptr);// 分配内存staticvoid*malloc();staticvoid*ordered_malloc();staticvoid*ordered_malloc(size_type n);// 归还内存staticvoidfree(void*ptr);staticvoidordered_free(void*ptr);staticvoidfree(void*ptr,std::size_t n);staticvoidordered_free(void*ptr,std::size_t n);// 释放内存staticboolrelease_memory();staticboolpurge_memory();};4.2 用法singelton_pool和pool的接口完全一致但其成员函数是静态的所以不需要声明singelton_pool的实例直接使用域操作符::来调用静态成员函数即可。代码示例#includeiostream#includeboost/pool/singleton_pool.hpp// 用于标记的空类structpool_tag{};// 第一个参数 Tag 用于标记不同的单件可以是空类// 第二个参数 RequestedSize 等同于 pool 构造函数中的 requested_size可以指示 pool 分配的内存块的大小typedefboost::singleton_poolpool_tag,sizeof(int)spl;// 定义内存池intmain(){// 分配一个整数内存块int*p(int*)spl::malloc();// 释放内存spl::release_memory();return0;}编译运行# 编译g-osingelton_pool_demo singelton_pool.cpp# 运行./singelton_pool_demo