(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,也可能是由于印刷原因,本段代码已经加以抹平。