二级空间配置器、空间配置器的默认选择、再次封装、对象的构造与释放

内存池

内存池:一块大的内存空间+对空间的管理机制。

1.提前准备好一块大的内存块备用,如果用户需要空间的时候,不需要通过malloc每次向系统索要,直接从备用大块内存中来进行获取。

2.不会频繁向系统索要小的内存块。解决内存碎片问题、申请空间效率低问题。不会浪费额外的空间。

3.用户将空间使用完成后,从谁跟前借,用完之后就还给谁。
对于用户归还的空间,内存池没有办法直接将小块内存连接到大块内存上。是因为哪块空间先归还是不一定的。
因此内存池必须对用户归还的空间进行单独管理。

4.如果用户现在需要空间,优先从已经归还的小块空间对应的链表中找合适的内存块进行分配。如果没有找到,再从大块内存中进行申请。
因为如果每次从大块内存中分配,会导致大块内存被分割成许多小块内存。如果将来用户需要更大的内存块,可能就不会分配成功了。

5.但如果按照链表的方式进行分配的话,链表中挂的都是非常小的内存块。解决了系统外部碎片问题,又引入了程序中的内部碎片。

二级空间配置器、空间配置器的默认选择、再次封装、对象的构造与释放_第1张图片

SGI-STL中二级空间配置器设计

SGI-STL中的二级空间配置器使用了内存池技术,但没有采用链表的方式对用户已经归还的空间进行管理(因为用户申请空间时在查找合适的小块内存时效率比较低),而是采用了哈希桶的方式进行管理。哈希桶中的内存块是可以重新分配的。SGI-STL将用户申请的内存块向上对齐到了8的整数倍。

二级空间配置器、空间配置器的默认选择、再次封装、对象的构造与释放_第2张图片

大致思想

void* refill(size_t size / * size是8的倍数 * / )
{
1.向内存池中更大的内存块索要空间:20个size字节的小块内存
nobjs=20;
chunk_alloc(nobjs,size);

2.nobjs=1;
将该小块内存返回给用户使用
nobjs>1 && nobjs <= 20;
将第一个内存块分配给用户使用,将剩余的nobjs-1个内存块挂在对应的桶中
}

void* chunk_alloc(size_t& objs,size_t size)
{
1.totalsize_nobjs * size;
计数nobjs个size字节的小块内存占用的总得字节数
2.leftsize=finish-start; //start和finish类型:char*
计算内存池中剩余的字节数的个数
3.分配内存:

  • a.leftsize>totalsize:内存池中剩余的空间可以提供totalsize字节的内存空间
    result=start;
    start+=totalsize;
    return result;
  • b.leftsize>=size:20个字节提供不了,但可以提供一块
    o

你可能感兴趣的:(C++)