示例1:在类中提前分配一块连续的内存池,减少cookie(分配内存时产生的头尾共8个字节,用于记录分配了多少内存)对内存的消耗

class Screen {
public:Screen(int x) : i(x) {}int getData() { return i; }void* operator new(size_t);void operator delete(void*, size_t);
private:static Screen* freeStore;//对象的内存地址static const int screenChunk;//要获取的Screen类的个数,内存数量 = sizeof(Screen) * screenChunkScreen* next;int i;
};
Screen* Screen::freeStore = nullptr;
const int Screen::screenChunk = 4;void* Screen::operator new(size_t size){Screen* p;//freeStore不为空表示预先拿到的内存还有位置if (!freeStore) {size_t  chunk = size * screenChunk;freeStore = p = reinterpret_cast<Screen*>(new char[chunk]);for (; p != &freeStore[screenChunk - 1]; ++p)p->next = p + 1;p->next = 0;}p = freeStore;freeStore = freeStore->next;//每调用一块内存往后移一位return p;
}void Screen::operator delete(void* p, size_t size) {static_cast<Screen*>(p)->next = freeStore;freeStore = static_cast<Screen*>(p);
}void test() {cout << "sizeof Screen: " << sizeof(Screen) << endl;//获取Screen大小Screen* p[100];for (int i = 0; i < 100; i++) {p[i] = new Screen(i);     //创建}for (int i = 0; i < 100; i++) {cout << "address: " << p[i] << "   i = " << p[i]->getData() << endl;}for (int i = 0; i < 100; i++) {delete p[i];              //销毁}
}

结果:screenChunk取值为4,所以每4个Screen对象的空间是连续的

 示例2:例1的优化版,加入embedded pointer

class Airplane {
private:struct AirplaneRep {unsigned long miles;char type;};union {AirplaneRep rep;Airplane* next;};
public:unsigned long getMiles() { return rep.miles; }char getType() { return rep.type; }void set(unsigned long m, char t) {rep.miles = m;rep.type = t;}void* operator new(size_t size);void operator delete(void*, size_t);
private:static Airplane* headOfFreeList;static const int BLOCK_SIZE;
};
Airplane* Airplane::headOfFreeList = nullptr;
const int Airplane::BLOCK_SIZE = 512;void* Airplane::operator new(size_t size){if (size != sizeof(Airplane)) {return ::operator new(size);} Airplane* p = headOfFreeList;if (p) headOfFreeList = p->next;else {size_t total_size = size * BLOCK_SIZE;Airplane* newBLOCK = reinterpret_cast<Airplane*>(new char[total_size]);for (int i = 1; i < BLOCK_SIZE-1; i++)newBLOCK[i].next = &newBLOCK[i + 1];newBLOCK[BLOCK_SIZE - 1].next = 0;p = newBLOCK;headOfFreeList = &newBLOCK[1];}return p;
}void Airplane::operator delete(void* deadObject, size_t size) {if (deadObject == 0) return;if (size != sizeof(Airplane)) {::operator delete(deadObject);return;}Airplane* carcass = static_cast<Airplane*>(deadObject);carcass->next = headOfFreeList;headOfFreeList = carcass;
}void test() {const int size = 100000;cout << "sizeof Airplane: " << sizeof(Airplane) << endl;//获取Screen大小Airplane* p[size];for (int i = 0; i < size; i++) {p[i] = new Airplane();p[i]->set(i, i % 3);}for (int i = 0; i < size; i++) {cout << "address: " << p[i] << "   i = " << p[i]->getMiles() << endl;}for (int i = 0; i < size; i++) {delete p[i];//销毁}
}

示例3:采用一个类来进行内存池,让所有类都能共用

 示例4:加入宏定义

示例5:标准库pool_allocator的实现

//******** pool_allocator 设计 ********enum { __ALIGN = 8 };
enum { __MAX_BYTES = 128 };
enum { __NRFEELISTS = __MAX_BYTES / __ALIGN };
template<bool threads, int inst>
class __default_alloc_template {
private://向上取8倍数static size_t ROUND_UP(size_t bytes) {return (((bytes) +__ALIGN - 1) & ~(__ALIGN - 1));}
private:union obj {union obj* free_list_link;};
private:static obj* volatile free_list[__NRFEELISTS];//存入16条free_list的头static size_t FREELIST_INDEX(size_t bytes) { //根据obj大小找到对应的free_list索引return (((bytes) +__ALIGN - 1) / __ALIGN - 1);}//分配内存池中的内存static void* refill(size_t n);//向系统获取内存放入内存池static void* chunk_alloc(size_t size, int& nobjs);static char* start_free;   //内存池起点static char* end_free;     //内存池终点static size_t heap_size;   //从系统中获取的内存大小public:static void* allocate(size_t n) {obj* volatile *my_free_list;obj* result;if (n > __MAX_BYTES) {return ::operator new(n);}my_free_list = free_list + FREELIST_INDEX(n);result = *my_free_list;if (0 == result) {void* r = refill(ROUND_UP(n));return r;}*my_free_list = result->free_list_link;return result;}static void deallocate(void* p, size_t n) {obj* q = (obj*) p;obj* volatile *my_free_list;if (n > __MAX_BYTES) {::operator delete(q, n);return;}my_free_list = free_list + FREELIST_INDEX(n);q->free_list_link = *my_free_list;*my_free_list = q;}//先不实现static void* reallocator(void* p, size_t old_sz, size_t new_sz);
};template<bool threads, int inst>
void* __default_alloc_template<threads, inst>::
chunk_alloc(size_t size, int& nobjs) {char* result;size_t total_bytes = size * nobjs;size_t bytes_left = end_free - start_free;//内存池够取需要的大小if (bytes_left >= total_bytes) {result = start_free;start_free += total_bytes;return result;}//内存池够一个或以上的obj大小else if(bytes_left >= size){nobjs = bytes_left / size;total_bytes = nobjs * size;result = start_free;start_free += total_bytes;return result;}//内存池连一个都obj大小都分不出来,先把剩余的内存分出去,再向系统要内存else {size_t bytes_to_get = 2 * total_bytes + (ROUND_UP(heap_size >> 4));//内存池还有内存,先把剩下的内存分出去if (bytes_left > 0) {obj* volatile *my_free_list = free_list + FREELIST_INDEX(bytes_left);((obj*) start_free)->free_list_link = *my_free_list;*my_free_list = (obj*) start_free;}//向系统要内存start_free = (char*) malloc(bytes_to_get);//start_free == 0 意味着系统分不出这么多内存了,需要向free_list里比size大的list要内存if (0 == start_free) {size_t i;obj* volatile *my_free_list;obj* p;for (i = size; i <= __MAX_BYTES; i + __ALIGN) {my_free_list = free_list + FREELIST_INDEX(i);p = *my_free_list;//要到了if (nullptr != p) {*my_free_list = p->free_list_link;start_free = (char*) p;end_free = start_free + i;return chunk_alloc(size, nobjs);}}//没要到,程序跑到这里应该会陷入死循环end_free = 0;start_free = (char*) ::operator new(bytes_to_get);}heap_size += bytes_to_get;end_free = start_free + bytes_to_get;return chunk_alloc(size, nobjs);}
}template<bool threads, int inst>
void* __default_alloc_template<threads, inst>::
refill(size_t n) {int nobjs = 2;//一般为20,为方便实验,每次取2块obj的大小char* chunk = (char*) chunk_alloc(n, nobjs);obj* volatile *my_free_list;obj*  result;obj* current_obj;obj* next_obj;int i;if (1 == nobjs) return chunk;my_free_list = free_list + FREELIST_INDEX(n);//在chunk内建立free_listresult = (obj*) chunk;*my_free_list = next_obj = (obj*) (chunk + n);for (i = 1; ; ++i) {current_obj = next_obj;next_obj = (obj*) ((char*)current_obj + n);if (i == nobjs - 1) {current_obj->free_list_link = 0;break;}else {current_obj->free_list_link = next_obj;}}return result;
}template<bool threads, int inst>
char* __default_alloc_template<threads, inst>::start_free = 0;
template<bool threads, int inst>
char* __default_alloc_template<threads, inst>::end_free = 0;
template<bool threads, int inst>
size_t __default_alloc_template<threads, inst>::heap_size = 0;
template<bool threads, int inst>
typename __default_alloc_template<threads, inst>::obj* volatile
__default_alloc_template<threads, inst>::free_list[__NRFEELISTS]= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};typedef __default_alloc_template<false, 0> myPoolAlloc;void test() {myPoolAlloc alloc;int* pi[6];//newfor (int i = 0; i < 6; ++i) {pi[i] = (int*) alloc.allocate(16);cout << pi[i] << endl;//打印地址}    //deletefor (int i = 0; i < 6; ++i) {alloc.deallocate(pi[i],16);}
}

结果:每次取2个区块,第一次内存池获取两倍的所需内存,所以应该有四块内存连续,结果正确

size_t bytes_to_get = 2 * total_bytes + (ROUND_UP(heap_size >> 4));

C++内存管理:内存池实现相关推荐

  1. LwIP 之六 详解动态内存管理 内存池(memp.c/h)

      该文主要是接上一部分LwIP 之 详解动态内存管理 内存堆(mem.c/h),该部分许多内容需要用到上一篇的内容.该部分主要是详细介绍LwIP中的动态内存池.整个内存池的实现相较于内存堆来说,还是 ...

  2. 内存管理-内存池的实现

    内存池的实现 1 前言 2 内存池的原理 2.1 内存利用链表进行管理 2.2 分配固定大小 2.3 按块进行内存管理 3 内存池的实现 3.1 内存池的创建 3.2 内存池的销毁 3.3 内存分配 ...

  3. LwIP 之五 详解动态内存管理 内存堆(mem.c/h)

    写在前面   目前网上有很多介绍LwIP内存的文章,但是绝大多数都不够详细,甚至很多介绍都是错误的!无论是代码的说明还是给出的图例,都欠佳!下面就从源代码,到图例详细进行说明.   目前,网络上多数文 ...

  4. dpdk内存管理——内存初始化

    *说明:本系列博文源代码均来自dpdk17.02* 1.1内存初始化 1.1.1 hugepage技术 hugepage(2M/1G..)相对于普通的page(4K)来说有几个特点: (1) huge ...

  5. [内存管理]内存池pool库

    pool库概述 如果之前学过操作系统的内存管理机制和内存分配算法等知识,那么就了解"内存池"的概念. 简单地说,内存池预先分配了一块大的内存空间,然后就可以在其中使用某种算法实现高 ...

  6. 【Linux 内核 内存管理】Linux 内核堆内存管理 ① ( 堆内存管理 | 内存描述符 mm_struct 结构体 | mm_struct 结构体中的 start_brk、brk 成员 )

    文章目录 一.堆内存管理 二.内存描述符 mm_struct 结构体 三.mm_struct 结构体中的 start_brk.brk 成员 一.堆内存管理 Linux 操作系统中的 " 堆内 ...

  7. Android之内存管理-内存监测-内存优化

    推荐文章:Android进程与内存及内存泄漏 Android之内存管理 1.1 Dalvik Dalvik虚拟机是Android程序的虚拟机,是Android中Java程序的运行基础.其指令集基于寄存 ...

  8. 11 操作系统第三章 内存管理 内存的基本知识 内存管理 内存空间扩充 连续分配管理方式

    文章目录 1 内存概念 1.1 内存作用 1.2 逻辑地址VS物理地址 1.3 装入的三种方式 1.3.1 绝对装入 1.3.2 可重定位装入 1.3.3 动态重定位装入 1.4 链接的三种方式 1. ...

  9. 纯干货,linux内存管理——内存管理架构(建议收藏)

    一.内存管理架构 内存管理子系统架构可以分为:用户空间.内核空间及硬件部分3个层面,具体结构如下所示: 1.用户空间:应用程序使用malloc()申请内存资源/free()释放内存资源. 2.内核空间 ...

  10. Linux内存管理内存映射以及通过反汇编定位内存错误问题

    提到C语言,我们知道C语言和其他高级语言的最大的区别就是C语言是要操作内存的! 我们需要知道--变量,其实是内存地址的一个抽像名字罢了.在静态编译的程序中,所有的变量名都会在编译时被转成内存地址.机器 ...

最新文章

  1. linux 修改系统时间和时区
  2. 转:开火,移动-大神Joel 也浮躁
  3. 躺平也要看,2022年计算机相关考试汇总
  4. 【MPS最佳实践】媒体工作流转码
  5. 寒武纪官宣25亿美元估值融资,也有AI芯片公司要被收购了
  6. 总结篇——git本地仓库上传更新到github
  7. ctfmon是什么启动项_Win7启动项找不到ctfmon进程无法正常使用输入法的解决方法...
  8. css实现文本溢出时显示省略号(单行)
  9. 1926. Nearest Exit from Entrance in Maze刷题笔记
  10. parse_url() vul
  11. unity android录制视频教程,Unity3d 录屏功能教程指南 | Cross Platform Replay Kit
  12. 《近匠》专访启明星辰安全研究中心副总监侯浩俊——物联网安全攻防的“线上幽灵”...
  13. css3 cale()属性介绍以及自适应布局使用方法
  14. kafka linux 脚本测试,kafka shell命令操作
  15. Linux终端编程--termios
  16. 抽象类中的非抽象方法调用自己的抽象方法
  17. MySQL运维进阶必备
  18. Biological network analysis with deep learning(使用深度学习的生物网络分析)
  19. android 开发常用apk工具
  20. Couldn‘t checkout HEAD: cannot lock ref git创建新分支异常处理

热门文章

  1. python压缩教程_如何使用Python压缩/解压缩zip文件?(代码示例)
  2. 东北电力计算机考研分数线,东北电力大学考研分数线_2021考研国家分数线什么时候出来...
  3. 老铁,你这什么键盘布局? 当然是Colemak
  4. 【历史上的今天】12 月 14 日:计算复杂性理论先驱出生;雅虎群组被关闭;W3C 召开第一次会议
  5. 孪生素数的最优解(应该)
  6. 操作系统之生产者与消费者
  7. 储存quill与php,import – 在扩展Quill方面遇到问题
  8. vue-quill-editor编辑器文本不居中问题处理
  9. 我有一个网络工程师的梦
  10. 虾皮规模毁约、毁 offer,操作太离谱了...