CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛

C++内存池的简单原理及实现-永久免费的源码丞旭猿

为什么要用内存池

C++程序默认的内存管理(new,delete,malloc,free)会频繁地在堆上分配和释放内存,导致性能的损失,产生大量的内存碎片,降低内存的利用率。默认的内存管理因为被设计的比较通用,所以在性能上并不能做到极致。

因此,很多时候需要根据业务需求设计专用内存管理器,便于针对特定数据结构和使用场合的内存管理,比如:内存池。

内存池原理

内存池的思想是,在真正使用内存之前,预先申请分配一定数量、大小预设的内存块留作备用。当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续申请新的内存,当内存释放后就回归到内存块留作后续的复用,使得内存使用效率得到提升,一般也不会产生不可控制的内存碎片。

内存池设计

算法原理:

预申请一个内存区chunk,将内存中按照对象大小划分成多个内存块block

维持一个空闲内存块链表,通过指针相连,标记头指针为第一个空闲块

每次新申请一个对象的空间,则将该内存块从空闲链表中去除,更新空闲链表头指针

每次释放一个对象的空间,则重新将该内存块加到空闲链表头

如果一个内存区占满了,则新开辟一个内存区,维持一个内存区的链表,同指针相连,头指针指向最新的内存区,新的内存块从该区内重新划分和申请

如图所示:

免费学习地址:C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂

【文章福利】:小编整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!~点击加入(832218493需要自取)

内存池实现

memory_pool.hppifndef_MEMORY_POOL_H_define_MEMORY_POOL_H_includeinclude template<size_tBlockSize,size_tBlockNum =10>class MemoryPool{public:	MemoryPool()	{std::lock_guard<std::mutex> lk(mtx);// avoid race condition// init empty memory pointer		free_block_head = NULL;		mem_chunk_head = NULL;	}~MemoryPool()	{std::lock_guard<std::mutex> lk(mtx);// avoid race condition// destruct automatically		MemChunk* p;		while (mem_chunk_head)		{			p = mem_chunk_head->next;			delete mem_chunk_head;			mem_chunk_head = p;		}	}void*allocate(){std::lock_guard<std::mutex> lk(mtx);// avoid race condition// allocate one object memory// if no free block in current chunk, should create new chunk		if (!free_block_head)		{			// malloc mem chunk			MemChunk* new_chunk = new MemChunk;			new_chunk->next = NULL;// set this chunks first block as free block head			free_block_head = &(new_chunk->blocks[0]);// link the new chunks all blocks			for (int i = 1; i < BlockNum; i++)				new_chunk->blocks[i - 1].next = &(new_chunk->blocks[i]);			new_chunk->blocks[BlockNum - 1].next = NULL; // final block next is NULL						if (!mem_chunk_head)				mem_chunk_head = new_chunk;			else			{				// add new chunk to chunk list				mem_chunk_head->next = new_chunk;				mem_chunk_head = new_chunk;			}		}// allocate the current free block to the object		void* object_block = free_block_head;		free_block_head = free_block_head->next;returnobject_block;	}void*allocate(size_tsize){std::lock_guard<std::mutex> lk(array_mtx);// avoid race condition for continuous memory// calculate objects num		int n = size / BlockSize;// allocate n objects in continuous memory				//FIXME:make sure n > 0		void* p = allocate();for(inti =1; i < n; i++)			allocate();returnp;	}voiddeallocate(void* p){std::lock_guard<std::mutex> lk(mtx);// avoid race condition// free object memory		FreeBlock* block = static_cast(p);		block->next = free_block_head; // insert the free block to head		free_block_head = block;	}private:// free node block, every block size exactly can contain one object	struct FreeBlock	{		unsigned char data[BlockSize];		FreeBlock* next;	};FreeBlock* free_block_head;// memory chunk, every chunk contains blocks number with fixed BlockNum	struct MemChunk	{		FreeBlock blocks[BlockNum];		MemChunk* next;	};MemChunk* mem_chunk_head;// thread safe related	std::mutex mtx;	std::mutex array_mtx;};endif// !_MEMORY_POOL_H_

main.cpp

includeinclude "memory_pool.hpp"classMyObject{public:	MyObject(intx): data(x)	{//std::cout << "contruct object" << std::endl;	}~MyObject()	{//std::cout << "destruct object" << std::endl;	}intdata;// override new and delete to use memory pool	void* operator new(size_t size);	void operator delete(void* p);	void* operator new[](size_t size);	void operator delete[](void* p);};// define memory pool with block size as class sizeMemoryPool gMemPool;void* MyObject::operatornew(size_tsize){//std::cout << "new object space" << std::endl;	return gMemPool.allocate();}voidMyObject::operatordelete(void* p){//std::cout << "free object space" << std::endl;	gMemPool.deallocate(p);}void* MyObject::operatornew[](size_tsize){//TODO:not supported continuous memoery pool for now	//return gMemPool.allocate(size);	return NULL;}void MyObject::operator delete[](void* p){	//TODO:not supported continuous memoery pool for now	//gMemPool.deallocate(p);}intmain(intargc,char* argv[]){	MyObject* p1 =newMyObject(1);std::cout<<"p1 "<< p1 <<" "<< p1->data<<std::endl;
	MyObject* p2 =newMyObject(2);std::cout<<"p2 "<< p2 <<" "<< p2->data <<std::endl;deletep2;
	MyObject* p3 =newMyObject(3);std::cout<<"p3 "<< p3 <<" "<< p3->data <<std::endl;
	MyObject* p4 =newMyObject(4);std::cout<<"p4 "<< p4 <<" "<< p4->data <<std::endl;
	MyObject* p5 =newMyObject(5);std::cout<<"p5 "<< p5 <<" "<< p5->data <<std::endl;
	MyObject* p6 =newMyObject(6);std::cout<<"p6 "<< p6 <<" "<< p6->data <<std::endl;deletep1;deletep2;//delete p3;	delete p4;	delete p5;	delete p6;getchar();return0;}

运行结果

p100000174BEDE0440 1p2 00000174BEDE0450 2p3 00000174BEDE0450 3p4 00000174BEDE0460 4p5 00000174BEDD5310 5p6 00000174BEDD53206

可以看到内存地址是连续,并且回收一个节点后,依然有序地开辟内存

对象先开辟内存再构造,先析构再释放内存

注意

在内存分配和释放的环节需要加锁来保证线程安全

还没有实现对象数组的分配和释放

声明:本文部分素材转载自互联网,如有侵权立即删除 。

© 版权声明
THE END
喜欢就支持一下吧
点赞0赞赏 分享
相关推荐
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容