下面是一個簡單的內存池思想的版本皆警,實現(xiàn)的思想如下:
通過維護一個freeNodeHeader鏈表爽彤。當要申請空間的時候,就從鏈表上面摘下一個結點诉植;要釋放一個空間的時候,就從將釋放的結點重新插入到鏈表里面昵观。
每個結點的大小是提前通過template傳入的倍踪,就是要分配的對象的大小。
Q1 : 為什么要寫一個內存池索昂,默認的malloc不挺好的嗎?
A1 :new 和 delete 是一個成本比較高的操作扩借,因為需要到堆上開辟和釋放空間椒惨。如果可以提前開辟好一大塊空間,然后潮罪,下次使用的時候康谆,就不需要可以直接使用內存池里面的空間,而不是去調用new和delete嫉到。這樣可以會更加高效沃暗。(使用線程池的目的也是這樣的)
Q2 : 自己設計的內存池會比malloc好嗎?會不會是負優(yōu)化?
A2 : 這個問題何恶,我也在思考孽锥。下面是我的思考(不一定是正確的答案)
自己設計內存池一定是基于一個特定的一個場景,如果在這個特定的場景下面,一個針對這個場景下設計出來的內存池也許會比默認的更好惜辑,但是如果這個場景是一個通用的場景唬涧,那我覺得默認的也許是更好的。
就像使用STL一樣盛撑,如果知道了里面存放的元素是int碎节,然后知道了元素數(shù)量,知道了對元素常用的操作抵卫。那么完全可以設計出一個比STL更高效的函數(shù)狮荔。但是如果這是一個通用的,可以大范圍被使用的場景介粘,那么可能STL是平均下來最好的結果殖氏。作為一個初學者,了解內存池的工作原理碗短,可以更好的理解一門編程語言的內存分配機制受葛。這對深入的學習非常有必要。我覺得還是應該學習學習的偎谁。哪怕你寫的內存池是一個垃圾总滩。
#include <iostream>
using namespace std;
template<int ObjectSize, int NumofObjects = 20>
class MemPool {
private:
struct FreeNode {
FreeNode* pNext;
char data[ObjectSize];
};
FreeNode * freeNodeHeader; //表示空閑鏈表
public:
MemPool() {
//init freeNodeHeader
this->freeNodeHeader = new FreeNode[NumofObjects];
for (int i = 0; i < NumofObjects - 1; i++) {
freeNodeHeader[i].pNext = &freeNodeHeader[i + 1];
}
freeNodeHeader[NumofObjects-1].pNext = NULL;
}
~MemPool() {
cout << " ~ 析構函數(shù) " << endl;
delete[] freeNodeHeader;
}
//函數(shù)的實現(xiàn)在下面
void* malloc() {
if (freeNodeHeader==NULL) { //空間沒有了
//分配一段新的空間
cout << "重新添加了空間" << endl;
FreeNode * newfreeNodeHeader = new FreeNode[NumofObjects];
for (int i = 0; i < NumofObjects - 1; i++) {
newfreeNodeHeader[i].pNext = &newfreeNodeHeader[i + 1];
}
newfreeNodeHeader[NumofObjects-1].pNext = NULL;
//于是又有了空間
freeNodeHeader = newfreeNodeHeader;
}
cout << "分配一個空間" << endl;
FreeNode * ret = freeNodeHeader;
freeNodeHeader = freeNodeHeader->pNext;
ret->pNext = NULL;
return ret;
}
void free(void* p) {
cout << "釋放一個空間" << endl;
FreeNode* pNode = (FreeNode*)p;
pNode->pNext = freeNodeHeader;//將釋放的節(jié)點插入空閑節(jié)點頭部
freeNodeHeader = pNode;
}
};
//一個實例類,用來作為測試
class ActualClass {
static int count;
int No;
public:
ActualClass() {
No = count;
count++;
}
void print() {
cout << this << ": ";
cout << "the " << No << " object" << endl;
}
void* operator new(size_t size);
void operator delete(void* p);
void* operator new[](size_t size);
void operator delete[](void *p,size_t size);
};
MemPool<4, 5> mp;
void* ActualClass::operator new(size_t size) {
cout << "size " << size << endl;
return mp.malloc();
}
void ActualClass::operator delete(void* p) {
mp.free(p);
}
void* ActualClass::operator new[](size_t size) {
cout << "size " << size << endl;
cout << "自定義的內存池并不支持申請多個空間,所以調用默認的malloc" << endl;
return malloc(size);
}
void ActualClass::operator delete[](void *p , size_t size)
{
cout << "調用默認的free" << endl;
cout<<"delete [] size : "<<size<<endl;
free(p);
}
int ActualClass::count = 0;
int main()
{
for (int i = 0; i < 3; i++) {
ActualClass* p = new ActualClass;
p->print();
}
ActualClass* p1 = NULL;
p1 = new ActualClass;
p1->print();
ActualClass* p2 = new ActualClass;
p2->print();
delete(p1);
ActualClass* p3 = new ActualClass;
p3->print();
//to-do
//目前內存池只能分配固定大小的空間巡雨,
//對于new[5] , 他申請內存的大小是 5*sizeof(ActualClass) + 4
// 但是實現(xiàn)的內存池只能分配固定大小闰渔,于是就使用malloc分配了
ActualClass* p4 = new ActualClass[5];
delete [] p4;
//ActualClass* p5 = new ActualClass[5];
//ActualClass* p6 = new ActualClass[5];
system("pause");
return 0;
};
分享另外一個版本:
基本的實現(xiàn)是和上面的一個相同的:
#include <iostream>
#include <windows.h>
using namespace std;
#include "MemoryPool.h"
#include "MTMemoryPool.h"
class CTest
{
public:
int m_n;
int m_n1;
void* operator new(size_t size)
{
void* p = s_pool->Alloc(size);
return p;
}
void operator delete(void* p, size_t size)
{
s_pool->Free(p);
}
static void NewPool()
{
s_pool = new CMemoryPool<CTest>;
//s_pool = new CMTMemoryPool<CMemoryPool<CTest>, CCriticalSection>;
}
static void DeletePool()
{
delete s_pool;
s_pool = NULL;
}
static CMemoryPool<CTest>* s_pool;
//static CMTMemoryPool<CMemoryPool<CTest>, CCriticalSection>* s_pool;
};
CMemoryPool<CTest>* CTest::s_pool = NULL;
//CMTMemoryPool<CMemoryPool<CTest>, CCriticalSection>* CTest::s_pool = NULL;
void testFun()
{
int i;
const int nLoop = 10;
const int nCount = 10000;
for (int j = 0; j<nLoop; ++j)
{
typedef CTest* LPTest;
LPTest arData[nCount];
for (i = 0; i <nCount; ++i)
{
arData[i] = new CTest;
}
for (i = 0; i <nCount; ++i)
{
delete arData[i];
}
}
}
int main(int argc, char* argv[])
{
{
unsigned int dwStartTickCount = GetTickCount();
CTest::NewPool();
testFun();
CTest::DeletePool();
cout << "total cost" << GetTickCount() - dwStartTickCount << endl;
}
system("pause");
return 0;
}
//http://www.cppblog.com/weiym/archive/2012/05/05/173785.html
Memory.h
template<typename T> //這里的T指的是 : CTest類
class CMemoryPool
{
private:
CMemoryPool<T>* m_pFreeList;
public:
enum { EXPANSION_SIZE = 32 };
CMemoryPool(unsigned int nItemCount = EXPANSION_SIZE)
{
ExpandFreeList(nItemCount);
}
~CMemoryPool()
{
//free all memory in the list
CMemoryPool<T>* pNext = NULL;
for (pNext = m_pFreeList; pNext != NULL; pNext = m_pFreeList)
{
m_pFreeList = m_pFreeList->m_pFreeList;
delete[](char*)pNext;
}
}
void* Alloc(unsigned int /*size*/)
{
if (m_pFreeList == NULL)
{
ExpandFreeList();
}
//get free memory from head
CMemoryPool<T>* pHead = m_pFreeList;
m_pFreeList = m_pFreeList->m_pFreeList;
return pHead;
}
void Free(void* p)
{
//push the free memory back to list
CMemoryPool<T>* pHead = static_cast<CMemoryPool<T>*>(p);
pHead->m_pFreeList = m_pFreeList;
m_pFreeList = pHead;
}
protected:
//allocate memory and push to the list
void ExpandFreeList(unsigned nItemCount = EXPANSION_SIZE)
{
unsigned int nSize = sizeof(T) > sizeof(CMemoryPool<T>*) ? sizeof(T) : sizeof(CMemoryPool<T>*); //取大的
//申請一段空間
CMemoryPool<T>* pLastItem = static_cast<CMemoryPool<T>*>(static_cast<void*>(new char[nSize]));
m_pFreeList = pLastItem;
for (int i = 0; i<nItemCount - 1; ++i)
{
pLastItem->m_pFreeList = static_cast<CMemoryPool<T>*>(static_cast<void*>(new char[nSize]));
pLastItem = pLastItem->m_pFreeList;
}
pLastItem->m_pFreeList = NULL;
}
};
MTMemoryPool.h (加鎖的版本)
#pragma once
class CCriticalSection
{
public:
CCriticalSection()
{
InitializeCriticalSection(&m_cs);
}
~CCriticalSection()
{
DeleteCriticalSection(&m_cs);
}
void Lock()
{
EnterCriticalSection(&m_cs);
}
void Unlock()
{
LeaveCriticalSection(&m_cs);
}
protected:
CRITICAL_SECTION m_cs;
};
template<typename POOLTYPE, typename LOCKTYPE>
class CMTMemoryPool
{
public:
void* Alloc(unsigned int size)
{
void* p = NULL;
m_lock.Lock();
p = m_pool.Alloc(size);
m_lock.Unlock();
return p;
}
void Free(void* p)
{
m_lock.Lock();
m_pool.Free(p);
m_lock.Unlock();
}
private:
POOLTYPE m_pool;
LOCKTYPE m_lock;
};
read more :
深入探究C++的new/delete操作符:
https://kelvinh.github.io/blog/2014/04/19/research-on-operator-new-and-delete/
C++ 實現(xiàn)高性能內存池 :
https://blog.csdn.net/xjtuse2014/article/details/52302083