STL 源码剖析allocator 深入(五)

2024-05-09 18:18

本文主要是介绍STL 源码剖析allocator 深入(五),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

此时感悟:在夜深人静的时候,感谢自己可以思考,可以成长。

今天在学校,看到了即将要来的招聘会,我知道,现在的自己必须面对现实,因为只有你得到了,才会留下来!


声明:参考书籍<STL 源码剖析>侯杰

stl 源码剖析 第二章,比较详细的简述了allocator,我在上面一篇也有简单的介绍!由于今天在看源码有很多 不解,所以特此来总结和学习。

allocator 概述

标准allocator需要实现rebind,allocate,deallocate,max_size和构造及析构函数一共六个函数

我就对不常见的加以介绍吧!

rebind

VC源码 

template<class _Ty,class _Alloc>class _Vector_val

有些VC源码 包含一个基类

template<class _Ty,class _Alloc>class _Vector_val: public _Container_base

再看看下面的代码

template<class _Ty,class _Alloc>class _Vector_val: public _Container_base{	// base class for vector to hold data
public:typedef typename _Alloc::template rebind<_Ty>::other _Alty;

可以看出是一个模板类,那么rebind 有什么作用呢?


typedef typename _Alloc::template rebind<_Ty>::other _Alty; 

整体来看是类型定义,假设现在我们这样使用vector<int>, 那么_Ty 即 int, _Ax 即 allocator<int>,由vector 类传递给 基类_Vector_val,则_Alloc 即allocator<int> ;

可以看到 allocator<void> 是allocator 模板类的特化, rebind<_Ty> 是成员模板类,other是成员模板类

中自定义类型,_Ty 即是int , 那么other 类型也就是allocator<int>, 也就是说_Alty 是类型 allocator<int> 。

_Alty _Alval; 即 基类定义了一个allocator<int> 类型的成员,被vector 继承后以后用于为vector 里面元素分配内存等操作。


Alocator 是内存分配器,STL在这个层面上进行开放是为了让用户/程序员有权选择不同的内存分配器。举例来说,Allocator_A和Allocator_B在内存分配方式上可能是不一样的,也就是说Allocator_A<int>和Allocator_B<int>所分配的内存很有可能是不一样的。 

假如有一个容器类MyVector, 它用的是Allocator_A<int>内存分配器,这个容器类很有可能需要double类型的分配器,而且要求对int和double类型的内存分配策略是一样的,这是rebind的意义就体现出来了。

总之一句话,rebind实现了对不同类型使用同一种内存分配策略的要求


2 allocate

SGI的allocator首先接受用户所需要的size_t,然后 调用allocate(其实是客户端这么写objalloc.allocate(n);),allocate向 freelist(__defalut_malloc_template的一个数据成员,型别为一个obj* volalite freelist[16],既是存储这16个列表的那个家伙),如果freelist没有内存(或者说它是空的,为初始化)那么调用 refill,refill从真正的SIG memory pool中取内存,取出做多20个客户端所需要的size_t大小的内存块,通过chunk_alloc,取出来后将其妆扮好(就是想这20块内存连接为 一个链表),上交给allocate享用

template char* __default_alloc_template<__threads, __inst>::_S_chunk_alloc(size_t __size, int& __nobjs)


默 认情况下__nobjs实参为20,而且是一个地址传递(引用传递).他做的工作可是相当相当的伟大.原始社会的时候,一切资源都相当的丰富(原始人从来 不担心石油危机),chunk_alloc从内存里面取出20块size_t大小的内存上交给refill,refill将其装配后,上交 freelist,allocate从freelist中取出一块上交给我(^_^),其实是我想allocate要内存,结果没有,allocate想 refill要内存,refill马上把chunk_alloc找来,于是内存有了.
  当然内存要节约使用,第一次我想要一个32字节的内 存,chunk_alloc找来了2*20*32个字节的内存,其中的20块上交给了refill,refill填充 freelist,freelist[3]存储其中19个,上交给客户端(我)一个.下一次我要一个8字节的内存,chunk_alloc又要找内存了, 不过上次找来的内存还没有用完(上次交了20*24,剩余20*24,也就是剩余480字节),而且足够上交refill的了(需要8*20=160), 他们我上交给他所需要的内存,不从系统堆(heap)里面取用内存(只有chunk_alloc这样的劳动人民知道花钱小心翼翼).这样美好的日子一直持 续着,突然有一天,chunk_alloc发现系统内存重要用完了,怎么办?怎么向refill交差?refill一再压迫 chunk_alloc.chunk_alloc于是去找freelist,freelist内部存储上尚未陪客户端(client)取走的内存,比如 freelist[3],中还有10块没有用完,也就是说有160个字节的内存,那么chunk_alloc看看内不能满足refill的最小需求(1块 size_t),然后毫无保留的上交上去.如果连freelist都没有内存了,chunk_alloc于是向同门兄弟 __malloc_default_alloc求助(调用它的allocate),再那里有内存不足的处理情况,或许就要std::bad_alloc 了!
  诚实的讲SGI的策略已经是异常的完美了,但是作为一个STL,只能是最完美的,其中还是存在一些不足,因为一个完美的memory_pool实在是很有难度的!!



这篇关于STL 源码剖析allocator 深入(五)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/974129

相关文章

深入理解C语言的void*

《深入理解C语言的void*》本文主要介绍了C语言的void*,包括它的任意性、编译器对void*的类型检查以及需要显式类型转换的规则,具有一定的参考价值,感兴趣的可以了解一下... 目录一、void* 的类型任意性二、编译器对 void* 的类型检查三、需要显式类型转换占用的字节四、总结一、void* 的

深入理解Redis大key的危害及解决方案

《深入理解Redis大key的危害及解决方案》本文主要介绍了深入理解Redis大key的危害及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一、背景二、什么是大key三、大key评价标准四、大key 产生的原因与场景五、大key影响与危

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

Java汇编源码如何查看环境搭建

《Java汇编源码如何查看环境搭建》:本文主要介绍如何在IntelliJIDEA开发环境中搭建字节码和汇编环境,以便更好地进行代码调优和JVM学习,首先,介绍了如何配置IntelliJIDEA以方... 目录一、简介二、在IDEA开发环境中搭建汇编环境2.1 在IDEA中搭建字节码查看环境2.1.1 搭建步

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get