内存管理–简单内存池的实现
目录
内存池的作用
-
减少空间占用
使用malloc分配内存时 , malloc会多分配一部分空间作为cookie
cookie的作用是记录分配的内存大小等信息, 方便free回收
C++中的::operator new(全局中的new)和::operator free,其内部都是调用malloc或者free
使用内存池, 可以让多次new申请的内存, 只需要分配malloc内存池时的cookie就可以了, 大大减少了cookie导致的内存浪费
-
减少频繁分配内存时的开销
自己实现内存池, 一次性分配较多的空间, 也就意味这多次new 申请内存时, 只需要一次调用malloc就可,减少了malloc的开销
同时delete时,将内存返回内存池, 也能提高内存的复用
内存池1.0
- 让类内含一个指针,在分配的时候方便链表使用
- 重载new操作符和delete操作符
- 含有静态成员内存池大小和当前头指针
[1.0]实现细节(易踩坑)
-
类内创建的静态成员变量需要在类外初始化
初始化方式例如
int dog::num = 0;
-
重载new和delete的时候返回值类型和参数类型有要求
new : 返回值类型必须是void*, 第一个参数必须是size_t
delete: 返回值类型必须是void, 第一个参数必须是void*,第二个参数必须是size_t
重载new和delete都需要是静态方法(因为使用该方法的时候 , 成员还未初始化) 但编译器默认为静态,加不加无所谓
-
申请内存池的时候,需要转换成类指针类型 , 转换会取其前几位地址
-
切块时利用指针++会增加一个类型的大小的特性,来填入链表
-
到末尾时要将最后节点的next置为nullptr!!!
否则当内存池为空时 , 继续进入下一个指针造成栈溢出(因为是通过判断指针是否为空来确定内存池是否为空)
-
delete重载时 , 也需要注意转换成类的类型,否则可能会造成回收的内存大小出错
-
for循环串成链表时条件中
cur != &header[MAX_BLOCK - 1]
要记得使用&取地址因为cur为指针,而header[MAX_BLOCK - 1]为最后一个成员的内容
[1.0]成品代码
class testMryCrl_1 {
private:
testMryCrl_1* next;
static int MAX_BLOCKS;
static testMryCrl_1* header;
public:
int data;
testMryCrl_1(int data = 0) :data(data) {
}
static void* operator new(size_t size) {
testMryCrl_1* ret;
//建立内存池
//判断当前内存池是否存在
if (header) {
}
else {
//内存池不存在,申请分配内存池
ret = header = static_cast<testMryCrl_1*>(::operator new(MAX_BLOCKS * sizeof(testMryCrl_1)));
//将申请的内存切块并串成链表
for (; ret != &header[MAX_BLOCKS - 1]; ret++) {
ret->next = ret + 1;
}