c++实现内存池并应用到STL容器

 

内存池:

     为了节省申请小块内存与释放小块内存时的开销,可以使用内存池,开始时根据需要申请一片较大的内存,在申请小块内存的时候从内存池中获取,在释放小块内存时,将内存放回内存池

内存池中的内存块:

    块的大小可以由内存池的编写者确定,一般为8的倍数:8,16,24,32,.....,128;单位为字节,相同大小的块通过指针串成一串(和单链表一样)

内存池的两个部分:

1.未区块化的内存:这是一片连续的内存,可以通过两个指针 begin和end 表示它

2.区块化的内存:区块化的内存通过链表的形式保存着

在申请小块内存的时候,是从区块内存链中取,而不是从未区块化的内存中取

内存池中的区块化:

    将大片的内存转换成许多内存块,如:将80个字节连续的内存,转换成10个大小为8字节的内存,同时需要将这10个内存块像链表一样串起来

为什么需要块?

    因为如果没有块,在回收内存的时候,回收的内存可能与内存池中未区块化的内存是不连着的,所有没办法通过简单的两个指针来表示他们。

实现:

#include <cstddef>
#include <cstdlib>
#include <climits>
#include <iostream>

#define ALIGN 8 				//最小的内存块及内存块增加的梯度 
#define MAX_BYTES 128			//最大的内存块 
template<int inst>
class memory_pool{
private:
	union block{
		union block* next;	//指向下一个区块 
		char d[1];
	};
	
	static block * volatile free_list[MAX_BYTES/ALIGN];	//数组元素指向区块化的链表 	
	static char *begin;			//未区块化的内存池的头 
	static char *end;			//未区块化的内存池的尾 
	static size_t heap_number;	//内存池向堆申请内存的次数

private:
	//将n上升到ALIGN的倍数 
	static size_t ALIGN_BYTES(size_t n){
		return ( (n+ALIGN - 1)/ALIGN) * ALIGN;
	}
	
	//根据n的大小,获取free_list的下标 
	static size_t FREE_LIST_INDEX(size_t n){
		return (n - 1)/ALIGN;
	}
	
	//从未区块化的内存中获取内存,或者向堆申请 
	static void *getMemory(size_t bytes, size_t& blocks){
		size_t bytes_remain = end - begin;		//现在还拥有的未区块化的内存,单位为字节 
		size_t bytes_need = bytes * blocks;		//需要获取的内存,单位为字节 
		void *result;
		
		
		//(1).可申请到所有需要的区块 
		if(bytes_remain >= bytes_need){
			result = begin;
			begin += bytes_need;
			return result;
		}
		
		//无法满足(1),但是可以申请1个或以上的区块 
		if(bytes_remain >= bytes){
			blocks = bytes_remain / bytes;		//可以获取的块数 
			result = begin;						
			begin += blocks * bytes;			//调整为区块化的内存的范围 
			return result;						
		}
		
		if(bytes_remain > 0){
			//连1个区块都无法申请,则将剩余的未区块化的内存区块化 
			block * volatile * free_list_now = free_list + FREE_LIST_INDEX(bytes_remain); 	
			block* new_block = (block *)begin;		//剩余的内存区块化 
			
			block* old_block = *free_list_now;		//链表拼接 
			new_block->next = old_block;			//链表拼接 
			*free_list_now = new_block;				//链表拼接 	 
			
			begin += bytes_remain;					//调整为区块化的内存的范围,该语句执行后表示已无未区块化内存 
		}
		
		
		//从堆中申请内存
		void * alloc_
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值