飙血推荐
  • HTML教程
  • MySQL教程
  • JavaScript基础教程
  • php入门教程
  • JavaScript正则表达式运用
  • Excel函数教程
  • UEditor使用文档
  • AngularJS教程
  • ThinkPHP5.0教程

C++内存管理:简易内存池的实现

时间:2021-12-14  作者:zyb993963526  

 什么是内存池?

在上一篇 C++内存管理:new / delete 和 cookie 中谈到,频繁的调用 malloc 会影响运行效率以及产生额外的 cookie, 而内存池的思想是预先申请一大块内存,当有内存申请需求时,从内存池中取出一块内存分配给目标对象。

初步实现

#include <iostream>
using namespace std;


class Screen {
public:
	Screen(int x) : i(x) { };
	int get() { return i; }

	void* operator new(size_t);
	void  operator delete(void*, size_t);

private:
	Screen* next;
	static Screen* freeStore;  //头指针
	static const int screenChunk;  //内存块数量
private:
	int i;
};

Screen* Screen::freeStore = 0;
const int Screen::screenChunk = 5;

void* Screen::operator new(size_t size){
	Screen *p;
	if (!freeStore) {  //内存池是空的
		size_t chunk = screenChunk * size;
		freeStore = p = reinterpret_cast<Screen*>(new char[chunk]);
		for (; p != &freeStore[screenChunk - 1]; ++p) {  //以链表的形式串联起来
			p->next = p + 1;
		}
		p->next = 0;
	}
	p = freeStore;
	freeStore = freeStore->next;
	return p;
}

void Screen::operator delete(void *p, size_t){
	//将内存块重新加入链表表头,同时调整头指针
	(static_cast<Screen*>(p))->next = freeStore;
	freeStore = static_cast<Screen*>(p);
}

//-------------
void test(){

	cout << "Size: " << sizeof(Screen) << endl;	

	size_t const N = 100;
	Screen* p[N];

	for (int i = 0; i < N; ++i)
		p[i] = new Screen(i);

	for (int i = 0; i < 10; ++i)  //输出地址观察
		cout << i << ": " << p[i] << endl;

	for (int i = 0; i < N; ++i)
		delete p[i];
}

int main(){
	test();
	return 0;
}

在上面的代码中设置一个内存池为5个内存块,当我们进行100次内存申请后,打印出前10个地址查看,可以看到前5个地址是连续的,后5个也是连续的,但中间由于重新申请了内存池,所以不是连续的。

但是这样的方法还存在着问题,那就是引入了额外的指针内存消耗,接下来将使用embeded pointer进行改进。

使用嵌入指针改进

上面就使用到了嵌入指针,一个 AirplaneRep 对象的大小为 8 字节,而一个 Airplane 的指针大小为 4 字节或 8 字节。在 32 位机器下, 指针可以借用 AirplaneRep 对象所占的 8 字节内存空间中的前 4 个字节,用来连接空闲的内存块。而当内存块需要被分配给对象时,此时它已从链表中移除,也就不需要指针来连接了。此时的 8 字节内存空间由 AirplaneRep 占据。当内存释放时也是同理,由于 Rep 和 next 不会同时用到,所以 embeded pointer 的做法可以减少内存消耗。

 参考:

  1. 【C++内存管理】内存管理实例 (二) —— Embeded pointer

  2. 嵌入式指针embedded pointer的概念以及用法

标签:编程
湘ICP备14001474号-3  投诉建议:234161800@qq.com   部分内容来源于网络,如有侵权,请联系删除。