C++定长内存块的实现

内存池

内存池是指程序预先从操作系统 申请一块足够大内存 ,此后,当程序中需要申请内存的时候,不是直接向操作系统申请 ,而是 直接从内存池中获取

同理,当 **程序释放内存 **的时候,并不真正将内存返回给操作系统,而是 返回内存池 。当程序退出( 或者特定时间 ) 时,内存池才将之前申请的内存真正释放。

程序关键

在进行地址归还的时候,必须要使用二级指针,因为获取到头部指针后需要记录下一个内存块的地址,这句话是理解下方程序的关键。

cpp 复制代码
#pragma once
#include <iostream>
#include <vector>
#include <time.h>
using std::cout;
using std::endl;

//定长内存池
//template<size_t N>//非类型模板参数
//class ObjectPool
//{};

//定长内存池
template<class T>
class ObjectPool
{
public:
	T* New() {
		size_t objsize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T);
		T* obj = NULL;
		// step2:申请空间有限从回收链表_freeList里拿
		if (_freeList) {
			//_freeList每个固定大小的头部字节中都有下一块内存的地址
			obj = (T*)_freeList;
			_freeList = *(void**)obj;
		}
		else {
			// step1
			// 小于1个指针给1个指针的大小
			if (_remainBytes < objsize) {
				_remainBytes = 128 * 1024;
				_memeory = (char*)malloc(_remainBytes);// 开个128kb的空间
				if (_memccpy == NULL) {
					throw std::bad_alloc();// 直接抛出异常
				}
			}
			obj = (T*)_memeory;
			_memeory += objsize;
			_remainBytes -= objsize;
		}
		new(obj)T;// 定位new,就是初始化这段空间
		return obj;
	}
	void Delete(T* obj) {
		// step1
		// 将这些空间一一连接起来,回收并利用
		obj->~T();// 显示调用析构函数
		*(void**)obj = _freeList;// *(void**)解引用就是void*的大小,也就是一个指针的大小
		//头插入
		_freeList = obj;
	}
private:
	char* _memeory = NULL;// 指向内存块 头部 的指针
	size_t _remainBytes = 0;// 指向内存块 剩余 的指针
	void* _freeList = NULL;// 指向回收链表的 头指针
};


struct TreeNode
{
	int _val;
	TreeNode* _left;
	TreeNode* _right;
	TreeNode()
		:_val(0)
		, _left(nullptr)
		, _right(nullptr)
	{
	}
};


void TestObjectPool()
{
	// 申请释放的轮次
	const size_t Rounds = 3;
	// 每轮申请释放多少次
	const size_t N = 10000;//1w
	std::vector<TreeNode*> v1;
	v1.reserve(N);
	size_t begin1 = clock();
	for (size_t j = 0; j < Rounds; ++j)
	{
		for (int i = 0; i < N; ++i)
		{
			v1.push_back(new TreeNode);
		}
		for (int i = 0; i < N; ++i)
		{
			delete v1[i];
		}
		v1.clear();
	}
	size_t end1 = clock();

	ObjectPool<TreeNode> TNPool;
	std::vector<TreeNode*> v2;
	v2.reserve(N);
	size_t begin2 = clock();
	for (size_t j = 0; j < Rounds; ++j)
	{
		for (int i = 0; i < N; ++i)
		{
			v2.push_back(TNPool.New());
		}
		for (int i = 0; i < N; ++i)
		{
			TNPool.Delete(v2[i]);
		}
		v2.clear();
	}
	size_t end2 = clock();
	cout << "new cost time:" << end1 - begin1 << endl;
	cout << "object pool cost time:" << end2 - begin2 << endl;
}

可以看到效率的提升

相关推荐
艾莉丝努力练剑10 小时前
【C++:C++11】C++11新特性深度解析:从可变参数模板到Lambda表达式
c++·stl·c++11·lambda·可变模版参数
同学小张12 小时前
【端侧AI 与 C++】1. llama.cpp源码编译与本地运行
开发语言·c++·aigc·llama·agi·ai-native
爱学习的小邓同学16 小时前
C++ --- 多态
开发语言·c++
招摇的一半月亮1 天前
P2242 公路维修问题
数据结构·c++·算法
f***01931 天前
CC++链接数据库(MySQL)超级详细指南
c语言·数据库·c++
合方圆~小文1 天前
球型摄像机作为现代监控系统的核心设备
java·数据库·c++·人工智能
椰萝Yerosius1 天前
[题解]2024CCPC郑州站——Z-order Curve
c++·算法
滨HI01 天前
C++ opencv简化轮廓
开发语言·c++·opencv
学习路上_write1 天前
FREERTOS_互斥量_创建和使用
c语言·开发语言·c++·stm32·单片机·嵌入式硬件
闻缺陷则喜何志丹1 天前
【SOSDP模板 容斥原理 逆向思考】3757. 有效子序列的数量|分数未知
c++·算法·力扣·容斥原理·sosdp·逆向思考