一:内存池的概念和实现原理概述
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方法并没有释放内存,也没有内存泄漏,申请的内存可重复使用。