Boost开发指南-3.8pool

pool

内存池预先分配了一块大的内存空间,然后就可以在其中使用某种算法实现高效快速的自定制内存分配。

boost.pool 库基于简单分隔存储思想实现了一个快速、紧凑的内存池库,不仅能够管理大量的对象,还可以被用做STL的内存分配器。某种程度上讲,它近似于一个小型的垃圾回收机制,在需要大量地分配/释放小对象时很有效率,而且完全不需要考虑delete。

pool库包含四个组成部分:最简单的pool、分配类实例的object_pool、单件内存池singleton_pool和可用于标准库的pool_alloc。

pool是最简单也最容易使用的内存池类,可以返回一个简单数据类型(POD)的内存指针。它位于名字空间boost,为了使用pool组件,需要包含头文件<boost/pool/pool.hpp>,即:

#include <boost/pool/pool.hpp>
using namespace boost;

pool组件本身没有外部依赖,但头文件 pool_fwd.hpp里的 singleton_pool间接依赖了 boost.system库,为了避免不必要链接错误,可以在 include 语句前定义宏BOOST_SYSTEM_NO_DEPRECATED。

类摘要

template <typename UserAllocator = default_user_allocator_new_delete>
class pool
{
    
    
public:
   explicit pool (size_type requested_size); //构造函数
   ~pool(); //析构函数
   size_type get_requested_size() const; //分配块大小
   void * malloc(); //分配内存
   void * ordered_malloc();
   void ordered_malloc(size_type n);
   bool is_from(void * chunk) const;
   void free (void * chunk); //归还内存
   void ordered_free(void * chunk);
   void free(void * chunks, size_type n);
   void ordered_free(void* chunks, size_type n);
   bool release_memory(); //释放内存
   bool purge_memory();
};

操作函数

pool的模板类型参数UserAllocator是一个用户定义的内存分配器,它实现了特定的内存分配算法,通常可以直接用默认的default_user_allocator_new_delete,它内部使用new[ ]和 delete[ ]分配内存。

pool的构造函数接受一个size_type类型的整数 requested_size,指示每次pool分配内存块的大小(而不是pool内存池的大小),这个值可以用get_requested_size()获得。pool会根据需要自动地向系统申请或归还使用的内存,在析构时,pool将自动释放它所持有的所有内存块。

成员函数malloc()和 ordered_malloc()的行为很类似c中的全局函数malloc(),用void*指针返回从内存池中分配的内存块,大小为构造函数中指定的requested_size。如果内存分配失败,函数会返回0,不会抛出异常。malloc()从内存池中任意分配一个内存块,而 ordered_malloc()则在分配的同时合并空闲块链表。ordered_malloc()带参数的形式还可以连续分配n块的内存。分配后的内存块可以用is_from()函数测试是否是从这个内存池分配出去的。

与malloc()对应的一组函数是free(),用来手工释放之前分配的内存块,这些内存块必须是从这个内存池分配出去的(is_from(chunk) == true)。一般情况内存池会自动管理内存分配,不应该调用free()函数,除非你认为内存池的空间已经不足,必须释放已经分配的内存。

最后还有两个成员函数:release_memory()让内存池释放所有未被分配的内存,但已分配的内存块不受影响;purge_memory()则强制释放pool 持有的所有内存,不管内存块是否被使用。实际上,pool 的析构函数就是调用的 purge_memory()。这两个函数一般情况下也不应该由程序员手工调用。

用法

pool很容易使用,可以像c中的malloc()一样分配内存,然后随意使用。除非有特殊要求,否则不必对分配的内存调用free()释放,pool会很好地管理内存。例如:

#define BOOST_SYSTEM_NO_DEPRECATED //避免链接boost.system库
int main()
{
    
    
	pool<> pl(sizeof(int)); //一个可分配int的内存池

	int* p = static_cast<int*>(pl.malloc()); //必须把void*转换成需要的类型
	assert(pl.is_from(p)); //测试是否分配出去

	pl.free(p); //释放内存池分配的内存块
	for (int i = 0; i < 100; ++i) //连续分配大量的内存
	{
    
    
		pl.ordered_malloc(10);
	}
} //内存池对象析构,所有分配的内存在这里都被释放

因为pool在分配内存失败的时候不会抛出异常,所以实际编写的代码应该检查malloc()函数返回的指针,以防止空指针错误,不过通常这种情况极少出现:

int *p = static_cast<int*>(p1.malloc());
if(p != nullptr)
  ...

关于pool<>没有更多的解释,因为它真的很容易使用,只需要注意一点:它只能作为普通数据类型如int、double等的内存池,不能应用于复杂的类和对象,因为它只分配内存,不调用构造函数,这个时候我们需要用object_pool。

代码示例

#define BOOST_SYSTEM_NO_DEPRECATED

#include <boost/pool/pool.hpp>
using namespace boost;

int main()
{
    
    
	pool<> pl(sizeof(int));

	int* p = static_cast<int*>(pl.malloc());
	assert(pl.is_from(p));

	pl.free(p);
	for (int i = 0; i < 100; ++i)
	{
    
    
		pl.ordered_malloc(10);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36314864/article/details/132061785