STL-ch2-空间配置器

android广告SDK原理详解(附源码) 广大的开发者吃糠咽菜开发了一两款APP,获取了一些流量后自然就会想到流量变现,一般情况下大家会选择到百度联盟或者Google Admob这些广告服务提供商注册开发者账号,在自己的APP里面加上几行广告位代码,集成他们的广告SDK包。然后谋事在人,成事在天,只有每天看报表查查收益。   也有一些开发者为了能够提高自己的变现水平,同时接入了好几家的sdk,哪家出的收益高一点我就出哪家的广告,但是这 阅读详情

STL空间配置器

空间配置器——《STL源码剖析》chapter2

2.1 STL标准规定的空间配置器的标准接口

  • STL规定的空间配置器的名称是allocator
  • 包含下列typedef:
    • value_type
    • pointer/const_pointer
    • reference/const_reference
    • size_type
    • difference_type
  • 包含allocator::rebind
  • 包含成员函数:allocate(), deallocate(), construct(), destroy()。这4个全是成员函数,作用分别是:配置空间,释放配置空间,构造对象,析构对象。
  • SGI实现的STL未遵守STL标准的规定,使用的是一个具有次配置能力(sub-allocation)的特殊配置器。

2.2 具有次配置能力的SGI STL空间配置器

2.2.1 SGI也实现了STL标准规定的std::allocator

但是不建议用(只是对operator new和operator delete做了简单封装)

2.2.2 SGI中的特殊配置器名字叫std::alloc

  • class Foo{...};
    Foo *pf = new Foo;
    delete pf;
    

    上面的new算式包含两阶段操作:1. 调用operator new配置内存,2. 调用Foo::Foo()构造函数对象。

    delete算式也包含两阶段操作:1. 调用Foo::~Foo()将对象析构,2. 调用operator delete释放内存。

  • 为了精密分工,STL配置器将这两阶段操作区分开来。内存的配置和释放由alloc的成员函数alloc::allocate()和alloc::deallocate()来负责,对象的构造和析构由全局函数::construct()和::destroy()来负责。

  • 标准规定,配置器定义于头文件<memory>中,<memory>包含两个文件:#include<stl_alloc.h>(这里面定义了一二级配置器)和#include<stl_construct.h>(这里定义了全局的::construct()和::destroy())。

2.2.3 构造和析构基本工具::construct()和::destroy()

  • ::construct():利用placement new在传入的地址上构造对象。
  • ::destroy():有多个版本。1. 接受一个指针类型:直接调用指针指向对象的析构函数;2. 接受两个迭代器,需要先判断类型的析构函数是否trival(无关紧要),如果trival就什么都不做,如果不trival就遍历,依次调用上一个版本的destroy()。

2.2.4 空间的配置与释放std::alloc

  • 考虑小区块造成的内存破碎问题,SGI设计了双层级配置器。
  • 第一级:直接使用malloc()和free()。
  • 第二级:
    • 如果配置区块大小超过128byte,直接用malloc()和free()。
    • 如果配置区块大小不足128byte,为降低额外负担,采用复杂的memory pool整理方式。

2.2.5 第一级配置器malloc_alloc

  • template<int inst>
    class __malloc_alloc_template__{...};
    //别名
    typedef __malloc_alloc_template__<0> malloc_alloc;
    
  • allocate()直接使用malloc()。

  • deallocate()直接使用free()。

  • 模拟C++的set_new_handler()以处理内存不足的状况。

2.2.6 第二级配置器

  • sub-allocation:每次配置一大块内存,并维护对应之自由链表(free-list)。下次若再有相同大小的内存需求,就直接从free-lists中拔出。如果客端释还小额区块,就由配置器回收到free-list中。

  • 第二级配置器会自动将内存需求量上调至8的倍数,并维护16个free-lists(分别管理8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128bytes的小额区块)

  • free-list节点的结构

    union obj{
        union obj * free_list_link;
        char client_data[1];
    };
    

    使用union,一物二用,每个节点不需要额外的指针来维护链表。

2.2.7 空间配置函数allocate()

  • 源码:

    // n must be > 0
    static void * allocate(size_t n)
    {
        obj * volatile * my_free_list;
        obj * result;
        // 大于128就调用第一级配置器
        if(n>(size_t)__MAX_BYTES){
            return (malloc_alloc::allocate(n));
        }
        
        //寻找16个free-lists中适当的一个
        my_free_list = free_list + FREELIST_INDEX(n);
        result = *my_free_list;
        if(result == 0){
            //没有可用free-list,准备重新填充free-list
            void *r = refill(ROUND_UP(n));
            return r;
        }
        
        //调整free-list
        *my_free_list = result->free_list_link;
        return (result);
    }
    
  • 第一步:找打n对应的free-list;第二步:将result指向这个free-list的开头;第三步:调整free-list。二三两步就是将一个区块从free-list中摘下来。

  • 如果没有可用的free-list,调用refill()重新填充free-list

2.2.8 空间释放函数deallocate()

  • 源码:

    //p 不可以是0
    static void deallocate(void *p, size_t n)
    {
        obj *q = (obj*)p;
        obj *volatile * my_free_list;
        
        // 大于128就调用第一级配置器
        if (n>(size_t)__MAX_BYTES){
            malloc_alloc::deallocate(p,n);
            return;
        }
        
        my_free_list = free_list + FREELIST_INDEX(n);
        //调整free-list,回收区块
        q->free_list_link = *my_free_list;
        *my_free_list = q;
    }
    

2.2.9 重新填充refill()

  • 当free-list没有可用区块的时候,refill()从内存池中获取新的空间。

  • 缺省获得20个区块大小的空间,若内存池空间不足,实际获取的区块可能不足20。

  • 源码

    //假设n已经上调至8的倍数
    template <bool threads, int inst>
    void* __default_alloc__template<threads,inst>::refill(size_t n)
    {
        int nobjs = 20;
        //调用chunk_alloc(),尝试获得nobjs个区块作为free-list的新节点
        //注意参数nobjs是pass by reference
        char* chunk = chunk_alloc(n,nobjs);
        obj * volatile * my_free_list;
        obj * result;
        obj * current_obj, * next_obj;
        int i;
        
        //如果只有一个区块,这个区块就分配给调用者用,free-list无新节点
        if(n==1) return (chunk);
        //否则准备调整free-list
        my_free_list = free_list + FREELIST_INDEX(n);
        
        //以下在chunk空间内建立free-list
        result = (obj*) chunk;	//这一块准备返回给客端
        //以下引导free-list指向新配置的空间
        *my_free_list = next_obj = (obj*)(chunk+n);
        //以下将free-list的各节点串联起来
        for(i=1;;i++){
            current_obj = next_obj;
            next_obj = (obj*)((char*)next_obj+n);
            if(nobjs-1 == i){
                current_obj->free_list_link = 0;
                break;
            }else{
                current_obj->free_list_link = next_obj;
            }
        }
        return (result);
    }
    

2.2.10 内存池

  • chunk_alloc()从内存池中取空间给free-list使用,在refill()中被调用。

  • template <bool threads, int inst>
    char*
    __default_alloc_template__<threads,inst>::
    chunk_alloc(size_t size, int& nobjs)
    {
        //···
    }
    
  • chunk_alloc()的格式如上面所示,根据传进来的size和nobjs分配空间。

  • 首先在__default_alloc_template__类中有两个指针:start_free和end_free,两个指针都是static char*格式,分别指向内存池起始位置和内存池结束位置。

  • chunk_alloc()以end_free-start_free判断内存池的水量,如果水量充足,就直接调出20个区块返回给free-list。

  • 如果水量不足以提供20个区块,但还足够提供一个以上的区块,就拨出这不足20个区块的空间出去。此时pass by reference的nobjs参数将被修改为实际能提供的区块数。

  • 如果内存池连一个区块空间都不够了,就调用malloc从heap中配置内存,为内存池注入源头活水以应付需求。

  • 万一山穷水尽,整个system heap空间都不够了,malloc失败,chunk_alloc就四处寻找有无“尚有未用区块,且区块足够大”之free-list。找到了就挖一块交出,找不到就调用第一级配置器(寄希望于第一级配置器的out-of-memory处理机制)。如果可以就成功,否则就抛出bad_alloc异常。

手把手教你用STM32CubeIDE移植Vector CCP驱动,实现与INCA的标定通信(附避坑指南) 本文详细介绍了如何在STM32CubeIDE环境下移植Vector CCP驱动,实现与INCA的标定通信。从开发环境准备、CAN外设配置到CCP协议栈移植和A2L文件生成,提供了完整的操作流程和常见问题解决方案,帮助工程师快速掌握基于CAN总线的标定技术。 阅读详情

相关推荐

外部ADC之AD7949——14bit、8通道、250k

在实际项目中,仅靠单片机内部的ADC采样,很有可能达不到实际采样精度,这个时候就需要外接外部ADC芯片进行采样,这些外部ADC一般都是SPI接口或者是并口。单片机通过SPI接口或并口读写芯片内部寄存器,配置参考极性、采样通道、低通滤波器带宽、基准电压源、通道序列器等。本文主要对ADI家的14bit、8通道、250k的ADC7949做一个总结,这款ADC在实际项目中使用,采样精度达到要求,读取时序有点点绕,但是是一款十分常用的ADC芯片。就是价格不太友好哈哈,一块芯片快60。

cyaya6的博客 6715

代码管理平台:github

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33936401的博客 1284

告别密码烦恼:用Windows Server NPS给公司Wi-Fi和有线网加一道MAC地址白名单(附H3C交换机配置)

本文详细介绍了如何利用Windows Server NPS(网络策略服务器)与H3C交换机实现MAC地址白名单认证,为企业Wi-Fi和有线网络提供零密码安全方案。通过配置NPS服务器、网络策略及H3C交换机联调,实现无感知认证体验,降低运维负担,同时满足审计追溯需求。适用于中小企业网络管理,提升安全性与便捷性。

weixin_42535703的博客 367

【理论学习/C++】《STL源码剖析》学习笔记:Ch2空间配置器

Ch2 空间适配器 2.1 空间配置器标准接口 必要接口 template<class T> class allcator{ public: typedef T value_type; //基类型 typedef T* pointer; //一级指针 typedef const T* const_pointer; //常指针 typedef T& reference; //引用 typedef const T& const_re

m0_51274130的博客 274

【导航理论&实战篇】四足机器人弹簧倒立摆(SLIP)动力学模型

认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长!本文先对四足机器人动力学模型-VMC、SLIP和浮动机体模型做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章四足机器人弹簧加载倒立摆(SLIP)动力学模型是一种用于描述和分析四足机器人在运动过程中动态特性的理论模型。这种模型将四足机器人的腿部简化为弹簧,而机器人的身体则被视为一个倒立摆,这样的抽象使得研究者能够更容易地分析和控制机器人的运动。提示:以下是本篇文章正文内容。

qq_35635374的博客 806

Windows 上安装 OpenCode 完全指南:从零到成功,人人能看懂!

跟着这篇教程,你应该已经成功在 Windows 上安装并运行了 OpenCode。步骤操作要点1安装 Chocolatey必须以管理员身份运行 PowerShell2安装 OpenCode3验证安装关闭并重新打开终端,输入4进入项目目录必须是 Git 仓库(git init5配置模型输入/connect,输入 API Key6开始使用输入问题测试最后的小建议如果没有 API Key,可以从 DeepSeek 或 Kimi 开始,有免费额度初次使用建议先在简单项目上测试。

专注于编程、AI、人工智能等多个领域内容研究和分析 3889

Ch2 空间配置器(allocator) ---笔记

2.1 空间配置器的标准接口 allocator的必要接口: allocator::value_type allocator::pointer allocator::const_pointer allocator::reference allocator::const_reference allocator::size_type allocator::difference_type ...

weixin_30505043的博客 152

Vue3 - [最强] 超详细 Element Plus 组件库主题颜色进行 “统一全局“ 替换,将默认的蓝色主题色更换为其他自定义颜色,覆盖原来的主题色改为自己的颜色(完美解决主题色不生效、没反应)

elementplus修改主题色,vue3+element-plus主题色更换,vue3vite如何修改扩展elementplus主题色样式,全局设置elementplus主题色,有什么办法可以直接全局修改主题色,对elementplus默认蓝色不满意怎么替换更改其他颜色,elementplus覆盖默认主题色,elementplus主题色官方文档,vue3中修改elementplus主题色,elementplus修改主题色不生效怎么办,elementplus如何修改主题颜色,eleme

🏆 前端领域优质创作者 1万+

【C++】C++ STL string 详解

本文详细介绍了C++ STL中的string类及其底层实现。主要内容包括:1) STL的六大组件(容器、算法、迭代器等)及其关系;2) string类的本质是字符数组,相比C字符串具有自动扩容等优势;3) string的历史渊源,它早于STL出现且接口设计存在冗余;4) string实际上是basic_string<char>的别名,支持不同字符编码类型;5) 深入解析ASCII、Unicode(UTF-8/16/32)和GBK等编码方案的区别,以及UTF-8兼容ASCII的特性。文章还比较了Windows

feng_qi0325的博客 416

Far planner 代码系列(33) 关于real_world_contour和contour_graph

我们知道far planner前部分的流程是这样子的: 对于特定的地图,如下: 我们要从surround_obs_cloud里抽取生成realworld_contour_,如下图所示: 在这时候,每个node的z坐标都是以机器人的高度定的。如图所示: 先去吃饭啦~待会回来在写 ...

博客 762

Transformer时间序列预测-多变量输入-单变量输出+多变量输出,完整代码数据,可直接运行

Transformer时间序列预测-多变量输入-单变量输出+多变量输出,完整代码数据,可直接运行

9794

Ch5 关联式容器(下)

5.7 hushtable 5.7.1 hushtable概述 开链:在每一个表格元素中维护一个list;hash function为我们分配某一个list,然后我们在那个list身上执行元素的插入、搜寻、删除等操作。 5.7.3 hashtable的迭代器 template <class Value, class Key, class HashFcn, class Extra...

weixin_30776863的博客 70

基于卷积神经网络的遥感图像地物分类

AI:89-基于卷积神经网络的遥感图像地物分类 基于卷积神经网络的遥感图像地物分类是一个令人兴奋的领域,它在环境监测、城市规划、农业、国防等领域具有广泛的应用。深度学习技术为我们提供了更准确、高效的工具,有望在未来进一步提高分类性能。在本文中,我们探讨了卷积神经网络的工作原理、数据准备、模型构建、训练和评估过程,并提供了多个代码示例。此外,我们讨论了地物分类的应用和挑战,以及未来的发展趋势。

一键难忘的博客 2717

Ch4 序列式容器(上)

4.1 容器的概观与分类 4.2 vector 4.2.3 vector的迭代器 vector的迭代器是普通指针,属于Random Access Iterator。 template <class T, class Alloc=alloc> class vector { public: typedef T value_type; ...

weixin_30545285的博客 85

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

C++提高编程(三)

本阶段主要针对C++泛型编程和STL技术做详细讲解,探讨C++更深层的使用

qq_46518480的博客 1589

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

【C++】unordered_set/unordered_map的使用和哈希表的实现

本文介绍了C++标准库中的无序容器unordered_set和unordered_map的使用方法及其实现原理。unordered_set是无序、去重的单值哈希容器,要求元素支持哈希转换和相等比较,平均操作时间为O(1)。unordered_map存储键值对,同样基于哈希表实现,支持高效查找但不保证顺序。文章对比了它们与有序容器set/map的差异,包括底层结构、元素要求和遍历特性,并提供了常用接口的代码示例,如insert、find、erase等。unordered_map还支持[]操作符访问,但需注意意

2501_90523001的博客 242

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

C++ 常见问题总结(11)

好处是:当前代码抛出异常,如果在当前函数栈帧没有找到相应的catch块,就会这个异常抛给调用方函数,调用方函数依然是这样处理的,如果有处理异常的catch代码块,就向下运行,如果没有,就继续抛给调用方,直到到main函数还没有处理再抛给系统,系统发现有异常没有处理,就中止了。如果在函数上有找到catch块,就继续运行。异常的栈展开!异常的好处是可以把代码中所有的异常抛到统一的地方进行处理(比如说抛到main函数中统一处理)!exit(0);

ljy的博客 348

怎样将QTableWidget控件的列标题的宽度设置为固定不可拖动的

QTableWidget的列标题和行标题默认显示的情况下,可以拖动两个相邻列(行)之间的分割线来改变列宽(行高),如何将这个列宽(行高)锁死,设置为不可拖动的呢? 针对我所用的版本——Qt5.9,可以如下操作: // 设置所有的列 ui-&gt;tableWidget-&gt;horizontalHeader()-&gt;setSectionResizeMode(QHeaderView::F...

github_38704428的博客 8977

关于EuRoc数据集双目相机之间的基线长度

EUROC数据集提供了双目和IMU数据,可是并没有找到关于双目相机基线长度的直接描述。 查看了一番关于该数据集的论文publisher,设备描述部分并没有关于这一点的细节。 不过数据集中提供了sensor.yaml文件,该文件中,有这个sensor关于Body的T_BS(齐次坐标形式的4×4矩阵,可以参考高博的书籍或者博客)。 根据坐标转换关系: T_C1C2=T_C1B * T_BC2,

github_38704428的博客 6557

[C/C++]中按位“与”“或”“异或”的优先级比“==”低

项目调试时发现一个小问题,由于优先级没有搞对,导致的Bug。关于运算符优先级的问题以前学习的时候就没有太放在心上,因为一直觉得这个东西背了也没啥用,写程序的时候实在不行多加几个括号不就完事儿了吗。道理是不错的,这次就是少加了括号导致了一个常见的小Bug。记录一下,以后注意。 在C/C++中,if 语句简直是太常用了,if 语句中的条件判断为真的时候执行下面的语句(块),否则就不执行这些语句(块)...

github_38704428的博客 3700

Qt中文乱码问题在4.x版本和5.x版本的解决方法

Qt程序中文经常乱码,虽然有QString::fromLocal8Bit()或者tr()函数可以将中文包起来,但是每个有中文的地方都输一遍还是有点麻烦,希望“一劳永逸”地解决。 在4.x版本中,可以使用QTextCodec类,在main函数一开始的时候做类似下面的设置: QTextCodec::setCodecForLocale("GBK"); QTextCodec::setCodecFor...

github_38704428的博客 445

我的sizeof(struct)探索之旅

对sizeof(struct)的再次认识

github_38704428的博客 321

[C++]深度探索C++对象模型——关于默认构造函数

原书第二章第一节的内容 关于Default constructor的概念:没有任何形参的constructor(注意,不是说编译器自动为类添加的才叫Default constructor)。 这一节主要讲了编译器什么时候为类添加Default constructor? 先说结论:四种情况下,编译器会自动合成implicit nontrivial default constructor。 带...

github_38704428的博客 295

设计模式学习笔记1——单例模式

单例模式(Singleton) 保证一个类仅有一个实例,并提供一个访问它的全局访问点。 代码:https://github.com/duyilong/Design-pattern/tree/master/Singleton 保证仅有一个实例:不允许随意new,将构造函数、复制构造函数、赋值运算符声明为私有private,注意,析构函数也要声明为私有。 全局访问点:静态的GetInsta...

github_38704428的博客 264

va_start 和 va_end

这是两个宏定义,定义位置在 &lt;STDARG.H&gt; 见到这两个宏的时候基本会有可变参数的函数调用。所以,要想知道这两个宏的作用,先看一下 C 语言的函数传参原理。 1. 函数参数个数不定时的情况 函数参数个数不定的时候,可以用省略号(三个点...)表示。 void foo( param_list, ... ); 2. 函数参数的入栈顺序 C 语言函数调用的时候,实参从右到左...

github_38704428的博客 250

编程小 Tips ,持续更新中

任何技能都讲究熟能生巧,包括编程。但是在敲代码的过程中,掌握一些“奇技淫巧”还是可以对提高生产力大有帮助的! 下面就记录下自己学习到的一些小 Tips,常用的快捷键就不多提了。 有些小技巧自己不注意可能永远不会发现,正如同事所说,有的东西,靠口口相传!   1. 区域选中 在 IDE 中,按住 [ALT] 键 ,拖动鼠标,可以框选内容,VS和Qt Creator均支持。 2. 高级替换...

github_38704428的博客 226
上一篇: bss段,data段、text段、堆(heap)和栈(stack)
下一篇: 设计模式学习笔记——结构型模式
dummy_bot
博客等级 码龄10年 35粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值