内存池01
通过我前面的讲解,你已经知道每调用malloc一次都会产生cookie或者其他消耗资源的东西,它们是占用内存的,总之,减少malloc 的调用总是好的。于是为了解决这个问题,内存池出场了。
假设你需要new 1000个对象,如果执行new 1000次,显然就意味着会执行malloc 1000次,而产生额外的资源比如cookie也就有1000次,而包含上下两个cookie,分别占4个字节。那1000次光cookie就占用2 x 4 x 1000 bytes. 所以现在的改进是一次new 1000个对象,new object[1000],那么此次只执行了一次malloc。其实这就是内存池。内存管理的目标也就是速度和空间。
接下来我们实现这个例子,并且作对比。请看代码。
class foo{
public:
foo() :a(0)
{
cout << "默认构造函数\n";
}
foo(int x)
{
a = x;
cout << "a:" << a << endl;
}
static void *operator new(size_t size)
{
foo *p = NULL;
if (!freestore)
{
size_t chunk = size*ncount;
//一次获得ncount个对象大小的空间
freestore = p = reinterpret_cast<foo *>(new char[chunk]);
for (int i = 0; i < ncount;i++)
{
p->next = p+1;
p++;
}
p->next = NULL;
}
//将要返回的内存用p接管
p = freestore;
//为了下一次获得内存做准备,指针下移
freestore = freestore->next;
return p;
}
static void operator delete(void *p)
{
//将回收的内存放到头节点。
(static_cast<foo *>(p))->next = freestore;
//将第一个内存指向回收的内存
freestore = static_cast<foo *>(p);
}
~foo()
{
cout << "~foo()\n";
}
public:
int a;
//int b;
foo *next{NULL};
static const int ncount;
static foo *freestore;
};
const int foo::ncount = 24;
foo *foo::freestore = NULL;
void main()
{
cout << sizeof(foo) << endl;
foo *afoo[10];
for (int i = 0; i < 10;i++)
{
afoo[i] = new foo(i + 1);
}
cout << "--------------华丽的分割线-----------------\n";
for (int i = 0; i < 10;i++)
{
cout << afoo[i] << endl;
}
for (int i = 0; i < 10;i++)
{
delete afoo[i];
}
system("pause");
}
看结果(重载new):
可以看到间隔为8.
看结果(没有重载new):
间隔48,上一节我们讲了,malloc的时候会产生一个32位字节的包,和两个上下cookie (占8个字节),在加类大小为8 故间隔为48.
但是这里还有一个问题,额外增加了一个指针next,它占用4个字节,到低值不值呢?或者该如何改进呢,欲知后事,请听下回!