内存池系列

博客介绍了实现单线程可变大小内存管理器,包含头文件和源文件,还提及固定大小对象内存池。作者表示会在闲暇时发布更多内存池系列内容源码,同时指出参考书籍代码有印刷问题并已修正。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(1)实现一个单线程可变大小内存管理器

头文件:

#ifndef MEMORYPOOK_H
#define MEMORYPOOK_H
class MemoryChunk {
public:
  MemoryChunk(MemoryChunk * nextChunk, size_t chunkSize);
  ~MemoryChunk();
  inline void* alloc(size_t size);
  inline void free(void* someElement);
  size_t spaceAvailable() 
  {
    return bytesAlreadyAllocated;   
  }
  MemoryChunk* nextMemChunk() { return nextChunk; }
  enum {DEFAULT_CHUNK_SIZE=4096};
private:
  void* mem;//
  MemoryChunk * nextChunk;
  size_t chunkSize;
  size_t bytesAlreadyAllocated;
};
class ByteMemoryPool {
public:
  ByteMemoryPool(size_t initSize = MemoryChunk::DEFAULT_CHUNK_SIZE);
  ~ByteMemoryPool();
  inline void* alloc(size_t size);
  inline void free(void* someElement);
private:
  MemoryChunk * listOfMemoryChunks;
  void expandStorage(size_t reqSize);
};

#endif

源文件

#include"MemoryPool.h"
MemoryChunk::MemoryChunk(MemoryChunk * nextChunk, size_t reqSize)
{
  chunkSize = (reqSize>DEFAULT_CHUNK_SIZE)?reqSize: DEFAULT_CHUNK_SIZE;
  MemoryChunk::nextChunk = nextChunk;
  bytesAlreadyAllocated = 0;
  mem = new char[chunkSize];
}
MemoryChunk::~MemoryChunk() { delete[]mem; }
//分配函数
void* MemoryChunk::alloc(size_t requestSize)
{
  void *addr = static_cast<void*> (static_cast<size_t*>(mem) + bytesAlreadyAllocated);
  bytesAlreadyAllocated += requestSize;
  return addr;
}
void MemoryChunk::free(void* doomed)
{
  //这里因为不需要重用以前分配的内存故不做释放,在析构函数最终会释放全部
}
ByteMemoryPool::ByteMemoryPool(size_t initSize)
{
  expandStorage(initSize);
}
ByteMemoryPool::~ByteMemoryPool()
{
  MemoryChunk* memChunk = listOfMemoryChunks;
  while (memChunk)
  {
    listOfMemoryChunks = listOfMemoryChunks->nextMemChunk();
    delete memChunk;
    memChunk = listOfMemoryChunks;
  }
  //memChunk = 0;//这一步因为memChunk是局部变量 很快被释放 所以可以不要 但是要有防止野指针的意识
}
void* ByteMemoryPool::alloc(size_t reqSize)
{
  size_t space = listOfMemoryChunks->spaceAvailable();
  if (space < reqSize)
  {
    expandStorage(reqSize);
  }
  return listOfMemoryChunks->alloc(reqSize);
}
void ByteMemoryPool::expandStorage(size_t reqSize)
{
  listOfMemoryChunks = new MemoryChunk(listOfMemoryChunks, reqSize);
}
void ByteMemoryPool::free(void* doomed)
{
  listOfMemoryChunks->free(doomed);
}

(2)固定大小对象内存池

//头文件 
#ifndef MEMORYPOOL_H
#define MEMORYPOOL_H
template <typename T>
class MemoryPool {
public:
 MemoryPool(size_t size = EXPANSION_SIZE);
 ~MemoryPool();
  inline void* alloc(size_t size);
  inline void free(void* someElement);
private:
  MemoryPool<T> *next;
  enum{ EXPANSION_SIZE =32};
  void expandTheFreeList(size_t howMany= EXPANSION_SIZE);
};
template<typename T>
MemoryPool<T>::MemoryPool(size_t size)
{
  expandTheFreeList(size);
}
template<typename T>
MemoryPool<T>::~MemoryPool()
{
  MemoryPool<T> *nextPtr = next;
  for (nextPtr = next; nextPtr != NULL; nextPtr = next)
  {
    next = next->next;
    delete[]nextPtr;
  }
}
template<typename T>
void*MemoryPool<T>::alloc(size_t size)
{
  if (!next)
    expandTheFreeList();
  MemoryPool<T>*head = next;
  next = head->next;
  return head;
}
template<typename T>
inline void MemoryPool<T>::free(void* someElement)
{
  // 这里并没有对someElement的合法性进行检查
  MemoryPool<T>* head = static_cast< MemoryPool<T>* >(someElement);
  head->next = next;
  next = head;
}
template<typename T>
void MemoryPool<T>::expandTheFreeList(size_t howMany)
{
  // 这里申请空间大小必须要取两者值最大 假设存放T 然后free 这时这段空间会用来存放next指针 相反也一样 故必须取两者最大
  size_t size = (sizeof(T) > sizeof(MemoryPool<T>*)) ? sizeof(T) : sizeof(MemoryPool<T>*);
  //这里的这段代码原文是(1) 但在gcc(7.4.0)编译时会报错 无法转换类型,这里其实只是要申请对应大小空间 那用(2)行不行?
  //不行 因为会导致递归申请空间 最后就是stack overflow 用(3)即可以
  //MemoryPool<T>* runner = static_cast<MemoryPool<T>*> ( new char[size]);(1)
  // MemoryPool<T>* runner = new MemoryPool<T>;导致递归(2)
  MemoryPool<T>* runner = static_cast<MemoryPool<T>*> (::operator new(size));//(3)
 
 

  next = runner;
  for (int i = 0; i < howMany; i++)
  {
   // runner->next = static_cast<MemoryPool<T>*> (new char[size]);这里是原文代码 但是会出错 改为下面代码即可 原因见上文
    runner->next = static_cast<MemoryPool<T>*> (::operator new(size));
    runner = runner->next;
  }
  runner->next = 0;//注意这里一定要初始化为NULL
}
#endif
//演示类 该类定义了一个静态MemoryPool<Rational>*指针 并且重载了new 和delete等 
class Rational
{
public:
  Rational(int a=0,int b=1):n(a),d(b){}
  void* operator new(size_t size)
  {
    return memPool->alloc(size);
  }
  void operator delete(void *doomed)
  {
    memPool->free(doomed);
  }
  static void newPool() { memPool = new MemoryPool<Rational>; }
  static void deleteMemPool() { delete memPool; }
private:
  int n;
  int d;
  static MemoryPool<Rational>*memPool;
};
MemoryPool<Rational>* Rational::memPool = 0;

 

(3)将在闲暇之余发布更多相关内存池系列内容源码

参考《提高C++性能的编程技术》原书pdf有一定bug,也可能是由于印刷原因,本段代码已经加以抹平。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值