C++ 内存池的实现(链式,线式)

📅 2026/6/30 1:17:43
C++ 内存池的实现(链式,线式)
线式连续 / 单调内存池和 链式空闲链表内存池 是内存池最基础的两大分类。一、两种内存池核心区别维度线式内存池Linear Pool链式内存池Chain Pool别名连续内存池、单调内存池、栈式内存池空闲链表内存池、块式内存池分配方式指针向后偏移顺序分配空闲链表管理随机分配释放方式只能整体释放不能单独释放可单独释放任意块可复用速度极快O (1)仅指针移动很快O (1)链表操作内存复用不可复用可复用适用场景临时对象、一次性分配、生命周期统一长期对象、频繁单独申请 / 释放实现难度最简单较简单功能特点线式像吃薯条按顺序吃吃完整包扔不能单独退一根链式像取珠子随便拿、随便还还回来能再用。二、线式内存池Linear Memory Pool核心原理预分配一整块连续内存用一个 ** 指针current** 记录当前分配位置分配时指针向后偏移对应大小释放时只能重置指针或销毁整个内存池无法单独释放。完整可运行代码#include iostream#include cstdlibusing namespace std;// 线式内存池顺序分配整体释放class LinearMemoryPool {private: char* pool_start; // 内存池起始地址 char* current; // 当前可用位置指针 size_t total_size; // 总大小public: LinearMemoryPool(size_t size) { total_size size; pool_start (char*)malloc(size); // 预分配整块内存 current pool_start; // 初始指向起始位置 }~LinearMemoryPool() { free(pool_start); // 一次性释放所有内存 }// 分配内存指针偏移极快 void* alloc(size_t size) { // 检查剩余空间 if (current size pool_start total_size) { cerr 线式内存池已满 endl; return nullptr; } void* res current; current size; // 指针后移 return res; }// 重置内存池指针归位复用整块内存 void reset() { current pool_start; }// 禁用拷贝 LinearMemoryPool(const LinearMemoryPool) delete; LinearMemoryPool operator(const LinearMemoryPool) delete;};// 测试int main() { std::cout \n--- 示例1线式内存池 ---\n; LinearMemoryPool pool(1024); // 创建1KB线式池int* a (int*)pool.alloc(sizeof(int)); char* b (char*)pool.alloc(100); *a 1024;cout 分配int *a endl; pool.reset(); // 重置整块内存复用 cout 重置后内存可重新分配 endl; return 0;}运行流程1. 创建1KB内存池 → pool_start指向堆内存current pool_start2. 分配int(4字节) → current从0偏移到43. 分配char[100] → current从4偏移到1044. 重置内存池 → current回到pool_start位置数据未清零但可被覆盖5. 程序结束 → 析构函数调用free释放整块内存线式内存池特点✅ 优点速度最快只有指针加减无复杂逻辑无内存碎片连续分配实现最简单无锁优化单线程下极致高效。❌ 缺点不能单独释放生命周期必须统一不能随机复用只能重置后整体复用空间利用率低中间无法释放容易浪费。三、链式内存池Chain Memory Pool核心原理预分配内存切成固定大小的块用 ** 空闲链表free_list** 串起所有空闲块分配从链表取一个块释放把块还回链表可复用。完整可运行代码#include iostream#include cstdlibusing namespace std;// 链式内存池空闲链表管理可单独释放/复用 class ChainMemoryPool { private: // 块联合体空闲时存指针使用时存数据 union Block { Block* next; // 空闲时存储指向下一空闲块的指针 char data[1]; // 使用时作为数据存储区 };Block* free_list; // 空闲块链表 void* pool; // 整块内存 size_t block_size; // 块大小public: ChainMemoryPool(size_t _block_size, size_t count 100) { // 块大小至少为指针大小64位系统8字节32位系统4字节 block_size _block_size sizeof(Block*) ? sizeof(Block*) : _block_size; // 预分配 pool malloc(block_size * count); // 预分配连续内存 // 构建链表 free_list (Block*)pool; // 空闲链表头指针始终指向第一个可用块 Block* cur free_list; for (size_t i 0; i count - 1; i) { cur-next (Block*)((char*)cur block_size); cur cur-next; } cur-next nullptr; }~ChainMemoryPool() { free(pool); }// 分配取链表头 void* alloc() { if (!free_list) return nullptr; Block* res free_list; free_list free_list-next; return res; }// 释放还回链表头可复用 void dealloc(void* ptr) { Block* block (Block*)ptr; block-next free_list; free_list block; }ChainMemoryPool(const ChainMemoryPool) delete; ChainMemoryPool operator(const ChainMemoryPool) delete; };// 测试 struct Test { int x; }; int main() { std::cout \n--- 示例2链式内存池 ---\n; ChainMemoryPool pool(sizeof(Test), 10); Test* t1 (Test*)pool.alloc(); Test* t2 (Test*)pool.alloc(); pool.dealloc(t1); // 单独释放 Test* t3 (Test*)pool.alloc(); // 复用t1的内存 cout t1地址 t1 t2地址 t2 t3地址 t3 endl; return 0; }执行流程图解初始状态构造完成后:free_list → [Block0] → [Block1] → [Block2] → ... → [Block9] → nullptrStep 1: Test* t1 (Test*)pool.alloc();free_list → [Block1] → [Block2] → ... → [Block9] → nullptr ↑ t1 (取出Block0)Step 2: Test* t2 (Test*)pool.alloc();free_list → [Block2] → ... → [Block9] → nullptr ↑ t2 (取出Block1)Step 3: pool.dealloc(t1); // 释放t1free_list → [Block0] → [Block2] → ... → [Block9] → nullptr ↑ 头插法归还Step 4: Test* t3 (Test*)pool.alloc(); // 复用free_list → [Block2] → ... → [Block9] → nullptr ↑ t3 t1 (复用Block0的地址)详细执行步骤步骤代码操作结果1ChainMemoryPool pool(sizeof(Test), 10);创建内存池块大小为sizeof(Test)共10个块预分配内存构建10个块的空闲链表2Test* t1 (Test*)pool.alloc();从链表头部取出一个块t1指向Block0free_list指向Block13Test* t2 (Test*)pool.alloc();再次分配t2指向Block1free_list指向Block24pool.dealloc(t1);将t1归还到链表头部Block0被插回链表头成为新的free_list5Test* t3 (Test*)pool.alloc();再次分配t3复用Block0地址与t1相同链式内存池特点✅ 优点可单独分配 / 释放灵活管理对象生命周期支持释放任意块可内存复用释放的块能再次使用无碎片块大小固定无外部碎片O (1) 效率分配释放都是链表操作。❌ 缺点比线式池稍慢链表指针操作只能管理固定大小块通用池需多级。