18.3 内存池概念、代码实现和详细分析

news2025/7/23 23:46:04

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

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<A*>(new char[realsize]);  //传统new,调用系统底层的malloc
		ptmplink = 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<A*>(phead))->next = m_freePosition;
	m_freePosition = static_cast<A*>(phead);
}

3、完整代码

#include<ctime>
#include <iostream>

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 MYMEMPOOL
	A* ppoint = (A*)malloc(size);
	++m_iMallocCount;
	++m_iCount;
	return ppoint;
#else
	A* ptmplink;
	if (m_freePosition == nullptr)
	{
		//为空,要申请一大块内存
		size_t realsize = m_sTrunkCount * size;  //申请m_sTrunkCount这么多倍的内存
		m_freePosition = reinterpret_cast<A*>(new char[realsize]);  //传统new,调用系统底层的malloc
		ptmplink = 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<A*>(phead))->next = m_freePosition;
	m_freePosition = static_cast<A*>(phead);
#endif
}

void func()
{
	clock_t start, end;  //包含头文件#include<ctime>
	start = 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<ctime>
#include <iostream>

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 MYMEMPOOL
	A* ppoint = (A*)malloc(size);
	++m_iMallocCount;
	++m_iCount;
	return ppoint;
#else
	A* ptmplink;
	if (m_freePosition == nullptr)
	{
		//为空,要申请一大块内存
		size_t realsize = m_sTrunkCount * size;  //申请m_sTrunkCount这么多倍的内存
		m_freePosition = reinterpret_cast<A*>(new char[realsize]);  //传统new,调用系统底层的malloc
		ptmplink = 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<A*>(phead))->next = m_freePosition;
	m_freePosition = static_cast<A*>(phead);
#endif
}

void func()
{
	clock_t start, end;  //包含头文件#include<ctime>
	start = 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方法并没有释放内存,也没有内存泄漏,申请的内存可重复使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/35474.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaEE高阶---SpringBoot的创建和使用

一 : 什么是SpringBoot? Spring的诞生是为了简化 Java 程序的开发的,Spring Boot 的诞生是为了简化 Spring 程序开发的.Spring Boot 是所有基于 Spring 开发的项目的起点 . Spring Boot 的设计是为了让你尽可能快的跑起来 Spring 应用程序并且尽可能减少你的配置文件 . Sprin…

深度学习系列2——Pytorch 图像分类(AlexNet)

1. 概述 本文主要是参照 B 站 UP 主 霹雳吧啦Wz 的视频学习笔记&#xff0c;参考的相关资料在文末参照栏给出&#xff0c;包括实现代码和文中用的一些图片。 整个工程已经上传个人的 github https://github.com/lovewinds13/QYQXDeepLearning &#xff0c;下载即可直接测试&a…

你了解PMP考试新考纲的内容吗?

2021年新版PMP考纲变化趋势 随着时代发展&#xff0c;PMP认证本身也通过改版不断调整定位&#xff0c;与全球项目管理趋势相匹配&#xff0c;确保在全球项目管理专业领域保持“黄金标准”。 新版本变化如下&#xff1a; 五大过程组变为三大板块。之前一直沿用的“启动、规划…

Transformer时间序列预测

介绍&#xff1a; 提示&#xff1a;Transformer-decoder 总体介绍 本文将介绍一个 Transformer-decoder 架构&#xff0c;用于预测Woodsense提供的湿度时间序列数据集。该项目是先前项目的后续项目&#xff0c;该项目涉及在同一数据集上训练一个简单的 LSTM。人们认为 LSTM 在…

阿里P8总结的Nacos入门笔记,从安装到进阶小白也能轻松学会

前言 都说程序员工资高、待遇好&#xff0c; 2022 金九银十到了&#xff0c;你的小目标是 30K、40K&#xff0c;还是 16薪的 20K&#xff1f;作为一名 Java 开发工程师&#xff0c;当能力可以满足公司业务需求时&#xff0c;拿到超预期的 Offer 并不算难。然而&#xff0c;提升…

GPC规范-SCP02

SPC02 流程 SPC02 指令 命令&#xff1a; 响应&#xff1a; 举例回复&#xff1a; 密钥分散数据&#xff1a; 0000FFFFFFFFFFFFFFFF Key Info&#xff1a; 20 02&#xff08;scp02&#xff09; Card挑战数&#xff1a; 001AC6619BE83082 Card加密值&#xff1a; 7…

leetcode刷题(133)——剑指 Offer 07. 重建二叉树

输入某二叉树的前序遍历和中序遍历的结果&#xff0c;请构建该二叉树并返回其根节点。 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 示例 1: Input: preorder [3,9,20,15,7], inorder [9,3,15,20,7] Output: [3,9,20,null,null,15,7]示例 2: Input: preord…

(十一)笔记.net学习表达式目录树Expression

&#xff08;十一&#xff09;笔记.net学习表达式目录树Expression1.什么是表达式目录树&#xff08;1&#xff09;Func和表达式的不同&#xff08;2&#xff09;表达式树拆解&#xff08;3&#xff09;自己拼装表达式目录2.动态拼装表达式目录和扩展应用3.解析表达式目录&…

阿里云服务器采用AMD CPU处理器ECS实例规格详解

阿里云服务器有AMD CPU处理器&#xff0c;阿里云服务器ECS通用型g7a、计算型c7a和内存型r7a采用2.55 GHz主频的AMD EPYCTM MILAN处理器&#xff0c;单核睿频最高3.5 GHz&#xff1b;通用型g6a、计算型c6a和内存型r6a采用2.6 GHz主频的AMD EPYCTM ROME处理器&#xff0c;睿频3.3…

MySQL读取的记录和我想象的不一致——事物隔离级别和MVCC

本篇是《MySQL是怎样运行的》读书笔记&#xff0c;主要分析并发的事务在运行过程中会出现一些可能引发一致性问题的现象。 文章目录1.事务的特性简介1.1 原子性&#xff08;Atomicity&#xff09;1.2 隔离性&#xff08;Isolation&#xff09;1.3 一致性&#xff08;Consistenc…

JUC基础

synchronized 复习虚假唤醒什么是虚假唤醒虚假唤醒产生的原因&#xff1f;解决虚假唤醒&#xff1f;Lock接口ReentrantLock 和 synchronized 的区别Lock 实现线程通信Lock 实现线程定制化通信集合线程安全ArrayListHashSetHashMapsynchronized 锁的范围多线程锁公平锁和非公平锁…

CameraMetadata 知识学习整理

一、涉及的相关代码路径 system/media/camera/src/camera_metadata.c // metadata的核心内容&#xff0c;包含metadata内存分配&#xff0c;扩容规则&#xff0c;update, find等 system/media/camera/src/camera_metadata_tag_info.c // 所有android原生tag的在内存里面sect…

22/11/24

1&#xff0c;单调队列&#xff1b; (76条消息) 单调队列专题_Dull丶的博客-CSDN博客 2&#xff0c;kmp算法&#xff1b; 先是自己和自己匹配&#xff0c;求出ne数组&#xff0c;然后和另一串匹配&#xff0c;进行求解&#xff1b; 循环里三步&#xff1a;while&#xff0c…

【Lilishop商城】No2-3.确定软件架构搭建二(本篇包括接口规范、日志处理)

仅涉及后端&#xff0c;全部目录看顶部专栏&#xff0c;代码、文档、接口路径在&#xff1a; 【Lilishop商城】记录一下B2B2C商城系统学习笔记~_清晨敲代码的博客-CSDN博客 全篇只介绍重点架构逻辑&#xff0c;具体编写看源代码就行&#xff0c;读起来也不复杂~ 谨慎&#xf…

【数据聚类】基于粒子群、遗传和差分算法实现数据聚类附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

【App自动化测试】(十)特殊控件Toast识别

目录1. toast介绍2. toast定位3. 实例演示前言&#xff1a; 本文为在霍格沃兹测试开发学社中学习到的一些技术写出来分享给大家&#xff0c;希望有志同道合的小伙伴可以一起交流技术&#xff0c;一起进步~ &#x1f618; 1. toast介绍 Toast&#xff0c;简易的消息提示框。为了…

CANdelaStudio-从入门到深入目录

前文介绍诊断协议那些事儿专栏,为大家深入介绍了ISO 14229各个服务的基础知识、请求与响应的报文格式,详情可查看:诊断协议那些事儿,从本专题开始,将由浅入深的展开诊断实际开发与测试的数据库编辑,包含大量实际开发过程中的步骤、使用技巧与少量对Autosar标准的解读。希…

HTML5学习笔记(四)

CSS3 颜色样式 在CSS3中&#xff0c;增加了大量定义颜色方面样式的属性&#xff0c;主要包括以下3种。 ▶ opacity透明度 ▶ RGBA颜色 ▶ CSS3渐变 opacity透明度 opacity属性取值是一个数值&#xff0c;取值范围为0.0~1.0。其中0.0表示完全透明&#xff0c;1.0表示完全不透…

I/O模型

网络IO的本质 网络IO的本质就是socket流的读取&#xff0c;通常一次IO读取会涉及两个阶段与两个对象&#xff0c;其中两个对象为&#xff1a;用户进程&#xff08;线程&#xff09;Process&#xff08;Thread&#xff09;、内核对象&#xff08;kernel&#xff09;,两个阶段为…

北方地区长乐市污水厂(150000m3d)工艺设计

目 录 1设计说明书 3 1.1概述 3 1.1.1设计题目 3 1.1.2设计任务 3 1.1.3设计阶段&#xff08;设计程度&#xff09; 3 1.1.4设计依据 3 1.1.5设计原始资料 3 1.1.6设计工作量 5 1.1.7设计要求 5 1.1.8 毕业设计日期 5 1.2 设计要求 6 1.2.1 设计原则 6 1.2.3 设计内容 6 1.3 水…