开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 10 天,点击查看活动详情
前言
在之前我们知道,使用malloc分配内存空间时,会得到一个cookie,而其又有很多我们暂时不需要的填充
当我们需要new很多对象时(多次调用malloc),那么就会造成很多的内存浪费
这时候就需要我们自己进行内存管理(自己开内存,使用内存,也就是需要利用重载实现)
内存管理的目标:
- 速度(要快)
- 减少malloc的调用次数(减少不必要内存空间的浪费)
pre-class allocator1
首先我们对operator new/delete进行重载
第一次开内存时,我们就开一个足够大的内存,同时进行内存切块,方便后面使用(这样下一个对象需要内存时,暂时就不需要malloc去分配,直接使用我们已经分配好的内存就好了,这样就可以减少cookie不必要的空间)
这里引入了一个概念:内存池,先创建出一大段连续空间的内存,然后将其切割成一小段一小段。
将创建的元素对象放在内存池切分好的各分段小内存片中,这样避免了多次调用new而造成生成多个带有cookie的内存空间。通过内存池的观念,可以生成一大段只带有两个头尾cookie的内存空间,而该一大段内存空间又被切分成每一小段的内存空间,且其中的每一小段内存空间片都可以共享这一整体的cookie信息。
那么怎么切分内存且记录下来? 答:我们使用一个链表进行记录。保存头指针,指向内存是下一块内存的地址,依次类推。
测试程序结果:
上图说明我们新new的对象在内存中是连续的,没有多余的内存开销
这里得看系统此时为我们分配的内存空间是否是连续的
这样做虽然减少了cookie的浪费,但是也引入了链表这一开销。
pre-class allocator2
对pre-class allocator1进行改进
pre-class allocator1适应用了一个指针,浪费空间
这个版本通过union关键字来减少使用next而所占耗的内存(没有懂,为啥减少了?)
static allocator
改进后依然存在一个问题:每次都需要在类中进行实现,重复工作太多
那么就:定义一个allocator类,用于完成opertator new/detlete操作
看看是如何使用的:
从上图可以看出,这样使用就方便多了...(先声明,再调用即可)
macro for static allocator
后面又发现,每次都要写myalloc,代码还是有重复性
那么就引入宏!
每次需要使用时,写上对应的宏即可
global allocator
STL为了适配不同的容器分配器,又进行了改进,如下(暂先了解)
总结
越学越难 ,得多看几遍
每看一遍都有新的领悟