✧(≖ ◡ ≖✿
目录
定长内存池
一:New()的初步设计
二:Delete()的设计
为什么不回退_memory?
完整代码gitee
定长内存池
有效、可分配内存块有两部分
1.有效内存池块。
2.自由链表管理区域。
构造函数
划分128kB给ObjectPool对象,异常抛出std::bad_alloc()。
New:为特定类型通过自由链表存储的/池内,分配固定空间大小。
Delete(const T* t):销毁指定目标。
一:New()的初步设计
_remainBytes:内存块内(自由链表内不计入大小)的剩余字节。
//申请 T* New() { int _sz = sizeof(T); //块内分配 if (_remainBytes <= _sz) { //剩余不足,新开大块 Alloc();//内存碎片问题不计 } T* obj = (T*)_memory; _memory += _sz; _remainBytes -= _sz; return obj; }初步架构:
template<typename T> class ObjectPool//无并发性,外界统一接口? { private: void Alloc()//bool?抛异常与bool分隔。bool会增加处理成本 { //划分块 _memory = (char*)malloc(128 * 1024);//1.此处malloc不够纯粹,"其底层封装"(划掉) //※ //2.使用SystemAlloc更纯粹,后期对比效率时替换 if (!_memory) throw std::bad_alloc();//大块划分失败,怎么捕捉?与构造函数无关? _remainBytes = 128 * 1024;//※ } public: ObjectPool() :_memory(nullptr), _remainBytes(0) { Alloc(); } //**成员先走初始化列表,后走函数体内** //申请 T* New() { int _sz = sizeof(T); //块内分配 if (_remainBytes <= _sz) { //剩余不足,新开大块 Alloc();//内存碎片问题不计 } T* obj = (T*)_memory; _memory += _sz; _remainBytes -= _sz; return obj; } private: char* _memory;//内存块头指针(128kB) int _remainBytes;//内存块内(自由链表内不计入大小)的剩余字节 };二:Delete()的设计
被删除任务删除头插进自由链表,由_freeList管理。
为什么不回退_memory?
销毁对象内存不一定连续。
设计图示
//释放,自由链表回收♻️ void Delete(const T* t) { //头插 *(void**)t = _freeList; //_freeList = t;//原因分析 _freeList = const_cast<T*>(t); }✨亮点:
1.为兼容x64、x86系统使用指针这一随系统大小变换的类型作为,限制访问区域。
2.const_cast<template T> (T t); 去const属性 // 非std域!!
完整代码gitee
#pragma once //using namespace std:: #include<iostream> /* 设计原则: 1.模板元编程。基于T大小申请、管理内存块。 意味着: 单一类型对象,New固定T大小无法指定。不像(void*) maollc(sizeof(size_t size)) 2.定长内存池设计的目标是:体会"池化技术",这一高效、广泛应用技术的底层设计原理。 //严格遵循"高内聚,低耦合"特性 */ template<typename T> class ObjectPool//无并发性 { private: void Alloc()//bool?抛异常与bool分隔。bool会增加处理成本 { //划分块 _memory = (char*)malloc(128 * 1024);//1.此处malloc不够纯粹,"其底层封装"(划掉) //※ //2.使用SystemAlloc更纯粹,后期对比效率时替换 if (!_memory) throw std::bad_alloc();//大块划分失败,怎么捕捉?与构造函数无关? _remainBytes = 128 * 1024;//※ } T* FreeAlloc() { //自由链表分配 //if (!_freeList)//err if (_freeList) { T* obj = _freeList; //头删 _freeList = *(void**)_freeList; _remainBytes = _remainBytes; return obj; } return nullptr; } public: ObjectPool() :_memory(nullptr), _remainBytes(0), _freeList(nullptr) { Alloc(); } //**成员先走初始化列表,后走函数体内** //申请 T* New() { //1.自由链表分配 return FreeAlloc(); //int _sz = sizeof(T);因为自由链表要管理,所以至少给4/8 int _sz = sizeof(T) >= sizeof(T*) ? sizeof(T) : sizeof(T*); //dpsk:一个类型T*的指针管理T的空间与管理4T空间有什么区别? // 访问限制、算术法固定 //2.块内分配 if (_remainBytes <= _sz) { //剩余不足,新开大块 Alloc();//内存碎片问题不计 } T* obj = (T*)_memory;// _memory += _sz; _remainBytes -= _sz; return obj; } //释放,自由链表回收♻️ void Delete(const T* t) { //头插 *(void**)t = _freeList; //_freeList = t;//原因分析 _freeList = const_cast<T*>(t); } private: char* _memory;//内存块头指针(128kB) int _remainBytes;//内存块内(自由链表内不计入大小)的剩余字节 T* _freeList;//自由链表头 }; //测试类型T class TreeNode { private: int _val; TreeNode* _left; TreeNode* _right; };感谢支持,长期连载
欢迎关注