C++附加篇: 空间适配器

这篇具有很好参考价值的文章主要介绍了C++附加篇: 空间适配器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C++附加篇: 空间适配器

 "我有时难过,却还有些抚慰和感动。"

一、我们来谈谈空间适配器        

(1) 什么是空间配置器?

        STL的六大组件,容器、算法、迭代器、适配器、仿函数,最后一个也就是"空间适配器"。

        所谓"空间适配器",顾名思义,就是对STL中各个容器的内存进行高效的管理。也许你会说,诶,我写了这么多的C++代码,为什么没有这个概念呢?或者说,为什么我们根本没有见到!这个空间适配器呢?

        然而事实上,不是说,我们没有使用,而是在我们使用诸如vector\list\deque时,我们的空间配置器是在默默地为我们进行工作。C++附加篇: 空间适配器

(2) 为什么需要空间适配器呢?

        我们使用堆上的空间,管它三七二十一,直接malloc 或者new不就得了?为什么还需要在空间申请的过程里,添加这一个适配器呢?对于使用者而言不麻烦吗?对于设计者而言,不也会给他们带来麻烦嘛?

        是的,如果我们仅单单从学习语言的角度来看,似乎无脑用malloc、new并没有啥有待商榷的地方,毕竟那本来就是提供给应用层调用的函数。

        但如果站在系统层面上,也许你在语言层调用malloc、new只是看到了单单的函数调用,并你接收到了来自函数的返回值"void*",你就可以针对这一块对空间上的内存块进行操作,仅此而已。你根本不知道操作系统在底层为你的行为做了哪些操作。

 唔,大概在底层,操作系统会为你做如下的事情:

        如果是在Windos下,malloc\new在底层会去调用 VirtualAlloc 向操作系统申请堆空间,如果是在Linux下,malloc、new会在底层调用 brk或者 mmap得到堆空间的起始地址。

        这似乎很符合我们的预期,与maloc、new相比,不就多调用了一次函数而已? 但事实真的是这样嘛?

        我们以在Linux环境下申请、释放空间例举:

我们以ARM64架构下来划分虚拟进程地址空间,编制从全0~全F。

高16位(0xFFFF 0000 0000 0000 ~ 0xFFFF FFFF FFFF FFFF) -->  内核地址空间

低16位(0x0000 0000 0000 0000 ~ 0x0000 FFFF FFFF FFFF) --> 用户地址空间

        不管我们使用什么样的函数,一旦涉及到要使用系统资源,例如: 堆空间、文件描述符、套接字描述符…… 其底层都需要访问系统提供的接口函数。然而,用户是不能直接执行内核代码的,而是需要切换成 内核用户才能执行代码,这个过程也叫做 "陷入内核",将用户态切换为内核态。显然,这个过程是很耗时的。

        不仅如此,Linux有自己内部的内存管理系统,如"伙伴系统",它需不需要维护系统堆空间上的资源?需要!难道它直接就把那块内存块扔给 用户?需不需要调剩余内存块的结构呢? 它需不需要对释放完的内存块进行管理,以避免内存碎片问题……

        有了上面的论述,空间适配器的出现,也就具有必然性。

malloc\new的不足之处

① 空间申请与释放需要用户自己管理,容易造成内存泄漏

频繁向系统申请小块内存块,容易造成内存碎片

频繁向系统申请小块内存,影响程序运行效率

④ 未考虑线程安全问题。

⑤ 代码结构比较混乱,代码复用率不高。

        因此需要设计一块高效的内存管理机制。


二、空间配置器窥探源码

(1) 空间适配器原理

        以上提及的用new、malloc最主要的一个问题是,"频繁"二字,在SGI版本中,空间配置器
以128作为 小块内存 与 大块内存的分割线。由此,其空间分配的结构分为两个的等级:一级空间配置器用于处理 大块内存的申请、释放,二级空间配置器用于处理 小块内存的申请、释放。
C++附加篇: 空间适配器

(2) 具体实现

一级适配器:

        一级适配器原理很简单,就是一个对malloc、free简单的封装。

C++附加篇: 空间适配器         例如这里一个simple_alloc 使用这个适配器。

C++附加篇: 空间适配器

二级适配器:

        我们在前面说SGI版本的Alloc,对于二级适配器而言,是一个管理这1~128这个范围的内存块。那么如何管理这一堆切小的小块内存呢,SGI采用了哈希桶的方式进行管理。但是,1~128,难道需要我们用开128个桶的空间来管理嘛?答案是否定的,第一个是从使用上来说,大多数开辟空间的大小都是4的正数倍,其次是,如果对内存空间的管理过于细腻,必定会造成一定空间浪费的问题。因此,SGI-STL将用户申请的内存块,向上对齐按照8byte。

C++附加篇: 空间适配器         此时,我们原本需要128个桶来唯一标识一个内存块对应的挂接位置,变为只需要16个桶。

  // 计算对齐后的 大小
  static size_t ROUND_UP(size_t bytes) {
        return (((bytes) + __ALIGN-1) & ~(__ALIGN - 1));
  }

    
  // 计算该字节大小 对应哪个桶
  static  size_t FREELIST_INDEX(size_t bytes) {
        return (((bytes) + __ALIGN-1)/__ALIGN - 1);
  }

        STI-STL提供了两个函数,分别可用来计算 对齐字节大小 和 内存块挂接的桶位置。

C++附加篇: 空间适配器

refill与chunk_alloc: 

C++附加篇: 空间适配器

        二级适配器还考虑了多线程环境下,Alloc的场景。C++附加篇: 空间适配器 

(3) 空间适配器与具体容器

C++附加篇: 空间适配器


三、 如何理解STL?

        STL的六大组件包括,算法、迭代器、容器、适配器、分配器(空间配置器)、仿函数。这几者有何关联呢?

C++附加篇: 空间适配器


总结:

        空间配置器其底层技术就是采用的池化技术,可以说就是一个小型的内存池。能在频繁申请小块内存的场景中,提高一定的性能。

        STL六大组件:算法、迭代器、容器、适配器、分配器(空间配置器)、仿函数。

本篇到此结束,感谢你的阅读

祝你好运,向阳而生~

C++附加篇: 空间适配器文章来源地址https://www.toymoban.com/news/detail-418502.html

到了这里,关于C++附加篇: 空间适配器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++适配器模式

    1 简介: 适配器模式是一种结构型设计模式,用于将一个类的接口转换为客户端所期望的另一个接口。适配器模式允许不兼容的类能够协同工作,通过适配器类来实现接口的转换和适配。 2 实现步骤: 以下是使用C++实现适配器模式的步骤: a. 定义目标接口:首先,确定客户

    2024年02月12日
    浏览(32)
  • 【C++】手撕 栈 & 队列(适配器)

    目录 一,stack 1,stack的介绍 2,stack 框架 3,push(const T x) 4,pop() 5,top() 6,size() 7,empty() 8,stack 测试 9,源代码 二,queue 1,queue的介绍 2,queue 框架 3,push(const T x) 4,pop() 5,front() 6,back() 7,size() 8,empty() 9,queue 测试 10,源代码 三,总结 1,stack 是一种容器适配器,专门用

    2024年04月15日
    浏览(30)
  • C++ [STL容器适配器]

    本文已收录至《C++语言》专栏! 作者:ARMCSKGT 前面我们介绍了适配器模式中的反向迭代器,反向迭代器通过容器所支持的正向迭代器适配为具有反向迭代功能的迭代器,本节我们介绍STL中另一种适配器: 容器适配器 ! 前面我们提到过STL适配器模式,关于适配器的解释: S

    2024年02月11日
    浏览(43)
  • C++之装饰器&适配器模式

    目录 一、装饰器模式 模式思想 模式简介 模式优点 模式缺点 代码实现 情景模拟 代码实现 运行结果 二、适配器模式 模式简介 介绍 优点 缺点 代码实现 情景模拟 模式简介 装饰器模式( Decorator Pattern )允许向一个现有的对象 添加新的功能 ,同时又不改变其结构。 这种类型

    2024年02月13日
    浏览(46)
  • 【C++】STL 算法 ⑩ ( 函数适配器 | 函数适配器概念 | 函数适配器分类 | 函数适配器辅助函数 | std::bind2nd 函数原型及示例 | std::bind 函数原型及示例 )

    在 STL 中 预定义了很多 函数对象 , 如果要 对 函数对象 的 参数 / 返回值 进行 计算 或 设置 , 可以 使用 \\\" 函数适配器 \\\" 实现上述需求 ; \\\" 函数适配器 \\\" 可以 将 已存在的 函数对象 转化为 另一种符合要求的 函数对象 ; \\\" 函数适配器 \\\" 定义在 functional 头文件 中 ; \\\" 函数适配器

    2024年02月02日
    浏览(63)
  • C++初阶—完善适配器(反向迭代器)

    目录 0. 前言 1、反向迭代器定义 2、反向迭代器需要实现的相关函数 3、反向迭代器分析 4、针对vector物理空间结构分析 5、针对list物理空间结构分析 6、反向迭代器适配器的实现及测试 7、有关迭代器的功能分类 本篇文章主要根据前面所实现的STL中支持迭代器的容器进行完善

    2024年02月09日
    浏览(37)
  • 【18】c++设计模式——>适配器模式

    c++的适配器模式是一种结构型设计模式, 他允许将一个类的接口转换成另一个客户端所期望的接口 。适配器模式常用于已存在的,但不符合新需求或者规范的类的适配。 在c++中实现适配器模式时,通常需要一下几个组件: 1.目标接口(Target interface):客户端所期望的接口,

    2024年02月07日
    浏览(46)
  • 【代码分析】初学解惑C++:函数适配器

    一、函数适配器是什么? (1). 简单来说函数适配器就是基于原有函数功能的基础上,再增加一些功能。跟pointer like class有些相似,都是想在原有的功能上,做更多的事情。 (2). 适配器的意思就是将某些已经存在的东西进行限制或者组合变成一个新的东西,这个新的东西体现一

    2024年02月09日
    浏览(42)
  • 适配器模式【结构型模式C++】

    1.概述      适配器模式 是一种结构型设计模式, 又称为变压器模式、包装模式(Wrapper) 将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。 2.结构 Target :适配器的内容,例如客户端使用的目标接口;

    2024年04月23日
    浏览(28)
  • C++ STL学习之【容器适配器】

    ✨个人主页: 北 海 🎉所属专栏: C++修行之路 🎊每篇一句: 图片来源 A year from now you may wish you had started today. 明年今日,你会希望此时此刻的自己已经开始行动了。 适配器(配接器)是 STL 中的六大组件之一,扮演着轴承、转换器的角色,使得 STL 中组件的使用更为灵活,

    2023年04月22日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包