五、C++内存管理机制 —— 分配器allocator(侯捷)

侯捷 C++八部曲笔记汇总 - - - 持续更新 ! ! !
一、C++ 面向对象高级开发
1、C++面向对象高级编程(上)
2、C++面向对象高级编程(下)
二、STL 标准库和泛型编程
1、分配器、序列式容器
2、关联式容器
3、迭代器、 算法、仿函数
4、适配器、补充
三、C++ 设计模式
四、C++ 新标准
五、C++ 内存管理机制
1、primitives
2、std::allocator
3、malloc/free
4、other allocators
5、loki::allocator
六、C++ 程序的生前和死后

👉 该课程能让你:从平地到万丈高楼!—— 侯捷
👉 做到:心中自有丘壑!
💪 源码之前,了无秘密!

演变过程:

per-class allocator

  1. 为了减少malloc的次数,使用我们重载operator new(如下图右上角),一次挖一大块,然后当作linked list 串穿起来,什么时候用到,直接给就行:
  2. 降低cookie的用量,由于一次malloc就有两个cookie占用8个字节,会增加浪费率;
  3. 所以使用 内存池不仅可以加快速度(速度考虑)还能降低利用率(空间考虑)
    在这里插入图片描述

union : 借用同一个东西的前四个字节当作指针来使用,从而减少内存的膨胀。

在这里插入图片描述

delete没有使用 free没有将内存还给操作系统,但不是内存泄漏(还都在自己的手上)。
如果要还的话,技术难点会非常高,这件事后面再讨论。

在这里插入图片描述

static allocator

如果还是像上面那样,任何需要分配器的class都需要给它写一个版本,重复性动作太多了!!!
从软件工程的角度考虑,同样的东西应该把它集中到一个地方上去,这样将来如果改变也很方便,改一个地方就行了。

面向对象领域我们不喜欢全局的东西,所以可以将上面的动作operator new / delete抽取出来,放到一个class里面,这个class就叫做allocator

在这里插入图片描述

可以将allocator想象成一个指针,指向一个链表;意思是:每个class里面都有专门为自己服务的小型的static(静态的)allocator,这个allocator里面有一个单向链表

在这里插入图片描述

  • 这比先前的设计干净多了,application classes不再与内存分配细节纠缠不清,所有相关细节都让allocator去操心,我们的工作是让application classes正确工作。

还有一种偷懒的实现方式,就是把上图黄色的这些东西定义成

在这里插入图片描述

global allocator

而标准库的allocator如下,它有16个自由链表:

在这里插入图片描述

标准库分配器 std::allocator

不同的编译器所附带的标准库里头的分配器做法可能都不一样,以下是当时三种主流编译器里面所带的分配器!

VC6 的标准分配器

可以对比最新的Visual Studio !

  • VC6 的 allocator 只是以 ::operator new::operator delete 完成 allocate()deallocate(),没有任何特殊设计。

  • 如下图右上角,容器的第二个模板参数都是 allocator

  • 分配是以对象元素为单位

在这里插入图片描述

BC5 的标准分配器

  • 和VC6相同,没有任何特殊设计。

在这里插入图片描述

GNU2.9 的标准分配器

在这里插入图片描述

使用的是allocalloc是一个class

  • 使用里面的静态函数 alloc::allocatealloc::deallocate
  • 512个字节,没有元素单元!

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

GNU4.9 的标准分配器

同样,没有任何特殊设计,和VC6,BC5一样。这个文件中已经说明,这个分配器没有用,容器的分配器不使用它!

在这里插入图片描述
在这里插入图片描述

GNU2.9 std::alloc

为什么要把他放在最后讲?因为侯老师认为它设计得最好。它和GNU4.9中的 __pool_allocator 相同。

在这里插入图片描述
设计是内存池的思想。

  • 16个指针指向16条链表 【只服务大小为8 ~ 128字节的元素,超过128字节就调用malloc,就不归这个pool管理了】,每条链表分配不同大小的内存空间,从左往右每一条链表间隔8个字节。
  • 理论上是这样的,但是在代码实现的时候,是首先申请一个大的内存块,然后在大的内存块上进行切分,所以不同链表之间会有连线
  • 每个链表会申请 8 ∗ n ∗ 20 ∗ 2 8*n*20*2 8n202 字节的内存空间,n 代表第 n 条链表 【也就是每一个块的大小为 8 ∗ n 8 * n 8n 个字节】 ,20 表示将内存最多切分成20个子内存块 【根据这个设计团队的经验设定的】 ,2 表示会申请 2 倍大小的内存用于战备池。这些内存空间是cookie free的。

⭐️ embedded pointers

  • 嵌入式指针:借用人家的前四个字节,当作指针。
  • 下图的obj就相当于指针。

在这里插入图片描述

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酷酷的懒虫

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值