内存池基础应用
本文只涉及内存池的基本应用,代码以及学习资料来源于网络,刚兴趣的网友可以搜一下。我这里只是总结一下自己的想法,做一个搬运工。
再复杂的工程也离不开基础应用的实战变化,这就像上学时的教材课后习题其实才是学生最应该掌握的。基础没打好直接上附加题,没什么意义。
内存池的基础应用 嵌入式指针的应用
内存池存在的意义
- 频繁的malloc会使内存碎片化,尤其是频繁的malloc小块内存,浪费的更加明显。
- 何为内存碎片化
- 内存池的实现手法不同,但核心思想相同
- 减少malloc的调用次数
- 减少malloc的此处,提高程序运行效率
- 内存池的实现原理
- 首先用malloc 申请出一大块内存,远大于实际要求。当然这一大块内存是连续的,当要分配的时候,从一大块内存中一点一点分配给你。
- 大块内存使用完毕后,再申请一块同样大的内存,再一点一点分配给你
- 如此往复
- 提高运行效率,减少内存浪费
内存池代码举例
- 这套代码的整体思想是,创建一大片空间,空间大小为 n * sizeof(class A);
- 后续每new出来一个class A类型的指针,都从这片连续内存池里取空间
- 池子用完了,可以自动申请出另一片大小相同的池子
- 池子中的位置都分配出去了,当有空位置 即有人要删除这个位子上的内容 则可以清空这个位置,这个位置在赤字中就为空,等待下一次分配
- 这个实例的缺陷是 如果A类是实战类,那么每次都要准备一个4字节指针,形成链路
class A
{
public:
static void * operator new(size_t size);
static void operator delete(size_t size);
private:
A * next;
static A * m_FreePos;
static int m_TrunckCount;
}
A * A::m_FreePos = nullptr;
int A::m_TrunckCount = 5;
void * A::operator new(size_t size)
{
A * tmplink;
if(m_FreePos == nullptr)
{
size_t realsize = m_TrucnkCount * size; //申请了多少个字节
m_FreePos = reinterpret_cast<A*>(new char[relsize]);//坑位已经帮你设置好了
tmplik = m_FreePos;
//分配出来的一大块内存,共5小块A类,彼此互联,供后续使用
//只处理了4个,最后一个要单独处理
for(;tmplink != &m_FreePos[m_TrunckCount-1]; ++tmplink)
{
tmplink->next = tmplink+1;
}
//这里循环出来时 最后一个
tmplink->next = nullptr;
}
tmplink = m_FreePos;
m_FreePos = m_FreePos->next;
return tmplink;
}
void A::operator delete(void *phead)
{
(static_cast<A*>(phead))->next = m_FreePos;
m_FreePos = static_cast<A*>(phead);
}
int main(int argc,char **argv)
{
for(int i = 0;i<50000000;i++)
{
A *pa = new A();
}
return 0;
}
嵌入式指针 – 指针的嵌入式应用
嵌入式指针是指 在类A中有一个结构体,结构体中只有一个元素,是一根指针
用这跟指针去嵌入到另一个类B中,可以理解为寄生,用这跟寄生在B类对象中的指针,链接到另一个相同的类B的对象中,形成串联的.
然这些串联的对象B,一起拉到A类构造的池子中。
- 思想: 在 A类中构造池子,把B类对象塞到池子里,池子的坑位一旦有对象了,这个坑位的内容就会被对象本身的内容塞满。坑位的obj->next 就没有指向了。
- 核心技巧: 池子的空间肯定是连续的。那么问题来了
- 问题一: 如何给池子划分坑位
- 不同于上一例子中,上一例子坑位已经划分好了
- 用obj* 划分坑位,精髓代码:
tmplink->next = (obj*)((char*)tmplink + size);
- 问题二: 如何把大象装进冰箱,如何把单体之间毫无关系的对象,塞到池子里的每一个坑位。
- 即把池子里的空位置返回给申请者即可
- 解决以上两个问题,就可以把内存池的基础应用理解明白
- 问题一: 如何给池子划分坑位
- 池子中的每个坑位只管大小,不管内容。分配完大小就完事儿了。剩下的内容留给对象自己去赋值。
- sizeof(B) > 4
class A
{
public:
void * allocate(size_t size)
{
obj * tmplink;
if(m_FreePos == nullptr)
{
//池子如何划分坑位
size_t realsize = m_TrunckCount * size;
m_FreePos = (obj*)malloc(realsize);
tmplink = m_FreePos;
//指处理4个坑位
for( int i = 0;i < m_TrunckCount -1; ++i)
{
tmplink->next = (obj*)((char*)tmplink + size);
tmplink = tmplink->next;
}
//最后一个坑位
tmplink->next = nullptr;
}
//把大象装进冰箱里
tmplink = m_FreePos;
m_FreePos = m_FreePos->next;
return tmplink;
}
void deallocate(void *phead)
{
((obj*)phead)->next = m_FreePos;
m_FreePosi = (obj*)phead;
}
private:
struct obj
{
struct obj * next;
}
int m_TrucnkCount = 5;
obj * m_FreePos = nullptr;
}
class B //类的大小要大于 4
{
private:
static A myalloc;
static void * operator new(size_t size)
{
return myalloc.allocate(size);
}
static void operator delete(void *phead)
{
return myalloc.deallocate(phead);
}
public:
int m_i;
int m_j;
}
int main(int argc,char **argv)
{
A * pa[100];
for(int i = 0; i < 15; i++)
{
pa[i] = new A();
pa[i]->m_i = 12;
pa[i]->m_j = 15;
}
return 0;
}