18.3 内存池概念、代码实现和详细分析
创始人
2024-02-15 14:50:51
0

一:内存池的概念和实现原理概述

malloc:内存浪费,频繁分配小块内存,浪费更加明显。

“内存池”要解决什么问题?

1、减少malloc()的次数,减少malloc()调用次数就意味着减少对内存的浪费
2、减少malloc()的调用次数,是否能够提高程序运行效率?
   会有一些速度和效率上的提升,但是提升不明显。

“内存池”实现原理:

1、使用malloc申请一个大块内存,当有分配需求的时候,从这一大块内存中一点点的进行分配,当这一大块内存分配快占满的时候了,再用malloc申请一大块内存,再一点点进行分配。
2、减少内存浪费,提高运行效率。

二:针对一个类的内存池实现演示代码

针对一个类的内存池A,A* pa = new A(),delete pa; 用内存池的手段实现new、delete对象。

1、内存池的operator new实现



void* A::operator new(size_t size)
{A* ptmplink;if (m_freePosition == nullptr){//为空,要申请一大块内存size_t realsize = m_sTrunkCount * size;  //申请m_sTrunkCount这么多倍的内存m_freePosition = reinterpret_cast(new char[realsize]);  //传统new,调用系统底层的mallocptmplink = m_freePosition;//把分配出来的这一大块内存(5下块),彼此要链起来,供后续使用for (; ptmplink != &m_freePosition[m_sTrunkCount - 1]; ptmplink++){ptmplink->next = ptmplink + 1;}ptmplink->next = nullptr;++m_iMallocCount;}ptmplink = m_freePosition;m_freePosition = m_freePosition->next;++m_iCount;return ptmplink;
}

2、内存池的operator delete实现


在这里插入图片描述

void A::operator delete(void* phead)
{(static_cast(phead))->next = m_freePosition;m_freePosition = static_cast(phead);
}

3、完整代码

#include
#include using namespace std;//#define MYMEMPOOL 1
class A
{
public:static void* operator new(size_t size);static void operator delete(void* phead);static int m_iCount;  //分配计数统计,每new一次,就统计一次static int m_iMallocCount;  //每malloc一次,就统计一次private:A* next;static A* m_freePosition;  //总是指向一块可以分配出去的内存首地址static int m_sTrunkCount;  //一次分配多少倍的该类内存
};int A::m_iCount = 0;
int A::m_iMallocCount = 0;
A* A::m_freePosition = nullptr;
int A::m_sTrunkCount = 5;  //一次分配5倍的该类内存作为内存池的大小void* A::operator new(size_t size)
{
#ifdef MYMEMPOOLA* ppoint = (A*)malloc(size);++m_iMallocCount;++m_iCount;return ppoint;
#elseA* ptmplink;if (m_freePosition == nullptr){//为空,要申请一大块内存size_t realsize = m_sTrunkCount * size;  //申请m_sTrunkCount这么多倍的内存m_freePosition = reinterpret_cast(new char[realsize]);  //传统new,调用系统底层的mallocptmplink = m_freePosition;//把分配出来的这一大块内存(5下块),彼此要链起来,供后续使用for (; ptmplink != &m_freePosition[m_sTrunkCount - 1]; ptmplink++){ptmplink->next = ptmplink + 1;}ptmplink->next = nullptr;++m_iMallocCount;}ptmplink = m_freePosition;m_freePosition = m_freePosition->next;++m_iCount;return ptmplink;
#endif
}void A::operator delete(void* phead)
{
#ifdef MYMEMPOOL free(phead);return;
#else(static_cast(phead))->next = m_freePosition;m_freePosition = static_cast(phead);
#endif
}void func()
{clock_t start, end;  //包含头文件#includestart = clock();for (size_t i = 0; i < 500'0000; i++){A* pa = new A();}end = clock();cout << "申请分配内存的次数为:" << A::m_iCount << ";实际malloc的次数为:" << A::m_iMallocCount << endl;cout << "用时(毫秒):" << end - start << endl;
}int main(int argc, const char* argv[])
{func();
}

三:内存池代码后续说明

#include
#include using namespace std;//#define MYMEMPOOL 1
class A
{
public:static void* operator new(size_t size);static void operator delete(void* phead);static int m_iCount;  //分配计数统计,每new一次,就统计一次static int m_iMallocCount;  //每malloc一次,就统计一次private:A* next;static A* m_freePosition;  //总是指向一块可以分配出去的内存首地址static int m_sTrunkCount;  //一次分配多少倍的该类内存
};int A::m_iCount = 0;
int A::m_iMallocCount = 0;
A* A::m_freePosition = nullptr;
int A::m_sTrunkCount = 5;  //一次分配5倍的该类内存作为内存池的大小void* A::operator new(size_t size)
{
#ifdef MYMEMPOOLA* ppoint = (A*)malloc(size);++m_iMallocCount;++m_iCount;return ppoint;
#elseA* ptmplink;if (m_freePosition == nullptr){//为空,要申请一大块内存size_t realsize = m_sTrunkCount * size;  //申请m_sTrunkCount这么多倍的内存m_freePosition = reinterpret_cast(new char[realsize]);  //传统new,调用系统底层的mallocptmplink = m_freePosition;//把分配出来的这一大块内存(5下块),彼此要链起来,供后续使用for (; ptmplink != &m_freePosition[m_sTrunkCount - 1]; ptmplink++){ptmplink->next = ptmplink + 1;}ptmplink->next = nullptr;++m_iMallocCount;printf("%s\n", "---------------------");}ptmplink = m_freePosition;m_freePosition = m_freePosition->next;++m_iCount;return ptmplink;
#endif
}void A::operator delete(void* phead)
{
#ifdef MYMEMPOOL free(phead);return;
#else(static_cast(phead))->next = m_freePosition;m_freePosition = static_cast(phead);
#endif
}void func()
{clock_t start, end;  //包含头文件#includestart = clock();for (size_t i = 0; i < 15; i++){A* pa = new A();printf("%p\n", pa);}end = clock();printf("%s\n", "---------------------");cout << "申请分配内存的次数为:" << A::m_iCount << ";实际malloc的次数为:" << A::m_iMallocCount << endl;cout << "用时(毫秒):" << end - start << endl;
}int main(int argc, const char* argv[])
{func();
}

此代码的delete方法并没有释放内存,也没有内存泄漏,申请的内存可重复使用。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...