c++实现简易内存池(解释最全)

一、简介

      内存池是一种用于管理动态分配的内存块的技术,它允许应用程序释放已经分配的内存块,而不是频繁地分配和释放内存。内存池通常用于大型应用程序,例如数据库连接池和虚拟内存管理。

        内存池的主要优点是减少内存分配和释放的开销,提高性能。通过复用已分配的内存块,内存池可以减少内存分配的次数,从而提高性能。内存池通常使用链表或哈希表来组织已分配的内存块,以便于查找和释放。

        内存池的实现通常包括以下部分:

        1. 内存池的配置和初始化:创建一个链表或哈希表来存储已分配的内存块,以及相关的统计信息,如已分配内存块的数量、最大和最小的内存块大小等。
        2. 内存块的分配:当用户请求分配内存块时,内存池根据需要分配一个新的内存块。如果内存池中有可用的内存块,则直接从池中分配。否则,为新分配的内存块分配更多的内存空间。
        3. 内存块的释放:当用户释放一个内存块时,将该内存块添加到内存池中,以便其他任务可以使用该内存块。这个过程还可能包括更新已分配内存块的统计信息。
        4. 内存池的维护:内存池需要定期维护,以确保其性能。这可能包括清理已释放的内存块,以避免内存泄漏。

        内存池在现代编程语言中已经成为了很多库的一部分,例如在Python中,内存池通常由`resource`模块提供。在Java中,内存池可以通过使用`java.util.concurrent.ThreadPooledExecutor`实现。在C++中,可以使用`std::shared_ptr`和`std::weak_ptr`来实现内存池。

二、流程

        1. 首先,使用了预处理器指令#pragma once和#ifndef NO9来确保只有一个头文件被包含,避免重复编译。

        2. 定义了一个名为test9的类,其中包含两个公共成员变量c_age和c_score,以及一个静态成员变量c_pool。

        3. 初始化内存池的函数initbool()被定义为静态函数,可以在类外部被调用。它使用malloc函数向内存申请18字节的内存,并用memset函数将内存初始化为0。如果内存申请成功,它会输出内存池的起始地址。

        4. 释放内存池的函数freepool()被定义为静态函数,可以在类外部被调用。它释放c_pool指向的内存池,并输出释放成功的信息。

        5. 构造函数被重载,用于初始化c_age和c_score成员变量,并在构造函数被调用时输出信息。

        6. 析构函数被重载,用于释放分配的内存。

        7. 新函数被重载,用于向内存池申请内存。如果内存池中没有空闲内存,它将直接向内存申请内存。

        8. 删除函数被重载,用于释放由new函数分配的内存。如果释放的是内存池中的内存,它将相应的空闲标志设置为0。

        9. c_pool是一个静态成员变量,用于存储内存池的起始地址。它的值在初始化内存池时被设置为分配的内存地址。

        10. #endif语句用于关闭条件编译指令NO9。

注意:这个示例中使用了自定义的内存分配和释放函数,而没有使用智能指针(auto_ptr)。这是因为智能指针在Visual C++中存在一些问题,而在其他编译器中则没有问题。在实际应用中,可以根据编译器的支持情况选择使用自定义的内存管理方法,或者直接使用智能指针。

三、示意图

        绿色是标志位,如果是0代表空闲,其他的情况代表忙碌

四、源代码头文件

#pragma once
#ifndef NO9
#define NO9
#include <iostream>
using namespace std;
class test9
{public:
	int c_age;
	int c_score;
	static char* c_pool; //存放内存池的起始地址
	//初始化内存池
	static bool initbool() {
		c_pool = (char*)malloc(18);//向内存申请18字节的内存
		if (c_pool == 0) return false;//申请失败,返回false
		memset(c_pool, 0, 18);//内存池中的内容初始化为0
		cout << "内存池起始地址是 :" << (void*)c_pool << endl;
		return true; 
	}
	//释放内存池
	static void freepool() {
		if (c_pool == 0) return; //如果内存池为空直接返回
		free(c_pool); //释放内存池给内存
		cout << "内存池已经释放" << endl;
	}

	test9(int age,int score) :c_age(age), c_score(score) {
		cout << "构造函数" << endl;
	}

	~test9() {
		cout << "构造函数" << endl;
	}
	//重载new函数,向内存池申请内存
	void* operator new(size_t size) {
		if (c_pool[0] == 0) {//判断第一块内存是否空闲,默认为0是空闲1是忙碌
			cout << "分配第一块内存  " << (void*)(c_pool + 1) << endl;
			c_pool[0] = 1;//第一块内存申请为忙碌
			return c_pool + 1;
		}

		if (c_pool[9] == 0) {//判断第二块内存是否空闲,默认为0是空闲1是忙碌
			cout << "分配第二块内存  " << (void*)(c_pool + 9) << endl;
			c_pool[9] = 1;//第二块内存申请为忙碌
			return c_pool + 10;
		}
		//若以上位置不可以用,直接向内存申请地址
		void* ptr = malloc(size);
		cout << "向内存申请的地址:" << ptr << endl;
		return ptr;
	}

	void operator delete(void* ptr) {
		if (ptr == 0)return;//对空指针delete是安全的
		if (ptr == c_pool + 1) {//若传进来的地址是内存池的第一个位置
			cout << "释放第一块内存  " << endl;
			c_pool[0] = 0;//申请第一块内存是空闲状态
			return;
		}
		
		if (ptr == c_pool + 10) {//若传进来的地址是内存池的第二个位置
			cout << "释放第二块内存  " << endl;
			c_pool[9] = 0;//申请第二块内存是空闲状态
			return;
		}

		//如果传进来的地址不属于内存地址则把他归还给内存
		free(ptr);
	}
};

char* test9::c_pool = 0;//对静态成员变量初始化
#endif // !NO9

五、源代码执行文件

#include "no9.h"
int main() {

	//初始化内存池
	if (test9::initbool() == false)
		cout << "内存初始化失败" << endl;
	cout << "内存初始化成功" << endl;
	//分配第一块内存
	test9* p1 = new test9(1, 2);
	cout << "p1的地址是:  " << p1 << "  年龄:  " << p1->c_age << "   分数:  " << p1->c_score << endl;
	
	//分配第二块内存
	test9* p2 = new test9(3, 4);
	cout << "p2的地址是:  " << p2 << "  年龄:  " << p2->c_age << "   分数:  " << p2->c_score << endl;

	//分配系统内存
	test9* p3 = new test9(5, 6);
	cout << "p1的地址是:  " << p3 << "  年龄:  " << p3->c_age << "   分数:  " << p3->c_score << endl;
	
	//释放第一块内存
	delete(p1);

	//分配第一块内存
	test9* p4 = new test9(7, 8);
	cout << "p4的地址是:  " << p4 << "  年龄:  " << p4->c_age << "   分数:  " << p4->c_score << endl;

	//释放第一块内存
	delete(p4);
	//释放第二快内存
	delete(p2);
	//释放系统内存
	delete(p3);
	test9::freepool();//释放内存池
	return 0;
}

六、执行结果

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值