18.3 内存池概念、代码实现和详细分析
创始人
2024-02-15 06:05:54
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方法并没有释放内存,也没有内存泄漏,申请的内存可重复使用。

相关内容

热门资讯

三亚警方通报:一男子持刀致3死... 央广网三亚12月6日消息(记者 陶淦)12月6日下午,三亚市公安局吉阳分局发布一起警情通报。 通报指...
会理市举办“法律明白人”专题培... 12月5日,会理市举办2025年“法律明白人”专题培训,进一步提升“法律明白人”的法治素养和业务能力...
大商股份有限公司关于修订《公司... 证券代码:600694 证券简称:大商股份 编号:2025-055 大商股份有限公司关于修订《公司章...
湖南株洲一无人驾驶汽车撞倒路人... 12月6日上午,有多名网友发布视频称,湖南株洲街头一辆哈啰无人驾驶汽车撞人,其中有一人被卷到了车底。...
因房屋租赁合同纠纷,江西中环国... 天眼查APP显示,近日,江西中环国际商业管理有限公司新增一则开庭公告,案由为“房屋租赁合同纠纷”,原...
因合同纠纷,黄靖芝起诉创匠信息 天眼查APP显示,近日,黄靖芝新增一则开庭公告,案由为“合同纠纷”,原告为黄靖芝,被告为厦门创匠信息...
8位专家点评“益心为公”志愿者... 12月5日是国际志愿者日。为学习贯彻党的二十届四中全会精神,深入践行习近平总书记致中国志愿服务联合会...
原创 越... 最近,日本常驻联合国代表山崎和之再次将目光投向台湾问题,并以强硬口吻要求国际社会共同反对中国的立场。...
下放仅2天后,开拓者官宣:从混... 12月6日,波特兰开拓者队官方宣布,将杨瀚森从发展联盟下属球队撕裂之城混音队召回。 12月4日,杨...
“选妃”玩法诱导打赏,低俗团播... 直播过程中穿着暴露,击打臀部、成员之间互相电击,采用送礼物排名“选妃”玩法……这些“擦边”行为被中央...