STL Allocator空间分配器二

2024-01-25 08:38
文章标签 空间 stl 分配器 allocator

本文主要是介绍STL Allocator空间分配器二,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

STL Allocator空间分配器二

 

今天把SGI提供的Allocator分配器仔细看了下,其设计还是相当精巧的。不过SGI的分配器已经脱离了STL标准,比如它就没有实现construct()destroy()成员函数。

 

简单malloc分配器

对于大于128B的空间直接就是malloc()free()了,没有什么特殊的;不过它还是仿造C++new handler形式设置了一个malloc exception handler;这样就和C++new行为相一致了,你可以设置malloc失败时的exception handler

 

Newdelete的分离

当对一个对象调用newdelete时,这两个操作都包含了两个阶段的动作:调用operator new分配空间,然后调用该对象的构造函数;调用该对象的析构函数,然后调用operator delete释放空间;SGI的分配器将这两步做了分离,内存分配和释放由函数alloc::allocate()alloc::deallocate()负责;物体构造和析构由函数construct()destroy()负责。

 

在调用destroy()函数同时释放n个对象(假设类型为T)时,SGI提供了方法可以判定对象是否有non-trivial destructor,如果没有则不必要循环为每个对象调用T::~T(),以提高效率,贴上源码,以便查看:

template <class T1, class T2>

inline void construct(T1* p, const T2& value) {

  new (p) T1(value);

}

template <class T>

inline void destroy(T* pointer) {

    pointer->~T();

}

template <class ForwardIterator>

inline void // 具有non trivial destructor

__destroy_aux(ForwardIterator first, ForwardIterator last, __false_type) {

  for ( ; first < last; ++first)

    destroy(&*first);

}

template <class ForwardIterator>

inline void __destroy_aux(ForwardIterator, ForwardIterator, __true_type) {} //空函数体,trivial destructor不需要调用

template <class ForwardIterator, class T>

inline void __destroy(ForwardIterator first, ForwardIterator last, T*) {

  typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor;

  __destroy_aux(first, last, trivial_destructor());

}

template <class ForwardIterator>

inline void destroy(ForwardIterator first, ForwardIterator last) {

  __destroy(first, last, value_type(first));

}

这需要借助于Traits编程技法来完成(原书3.7节)的:

typedef typename __type_traits<T>::has_trivial_destructor  trivial_destructor;

首先使用value_type()获取迭代器指向的物体类型,然后使用__type_traits<T>查看T是否有non-trivial destructor

 

简单分配器 simple_alloc

SGI为这原始分配器malloc和次级分配器alloc所作的一层简单封装;

 

次级分配器alloc

对于小于128B的请求采用了次级分配器;说白了就是SGI维护一个内存池来处理这些请求,以保证效率。它会将请求的字节数n圆整到8的倍数,比如如果请求的是14B的空间,其实获得的是16B;从这也可以得出SGI一共有16个链表需要维护,每个链表对应一个分配级别,对应的内存块大小分别是:81624128

为了不浪费存储空间,链表是一个union结构,像这样:

       union OBJ{

              union OBJ *free;

              char *data[1];

       };

free指针指向的是free链表中下一个空闲内存块,如果一个内存块被分配出去,就交给用户程序维护了,那么该块就没有必要继续维护了,知道再次收回(通过 free())。

分配和回收函数allocate()deallocate()就是简单的链表操作了,没有特别的地方。

比较复杂的就是内存池的维护函数chunk_alloc()函数,它最终还是需要通过malloc()来申请内存新的空间。

 

辅助函数

最后是几个操作为初始化空间的辅助函数,其内部基本都是通过调用全局construct()函数完成的。

 

对别人不是问题的问题

读到最后一直有个疑惑就是allocator没有实现construct()函数,那么它和容器是如何协同工作的呢?搜了搜源文件才发现,原来各容器都会显式调用全局函数construct()construct函数实际调用placement new),比如下面是list容器模板的一段代码:

 

typedef simple_alloc<list_node, Alloc> list_node_allocator;

link_type get_node() { return list_node_allocator::allocate(); }

void put_node(link_type p) { list_node_allocator::deallocate(p); }

  link_type create_node(const T& x) {

    link_type p = get_node();

    __STL_TRY {

      construct(&p->data, x);

    }

    __STL_UNWIND(put_node(p));

    return p;

  }

  void destroy_node(link_type p) {

    destroy(&p->data);

    put_node(p);

  }

 

这篇关于STL Allocator空间分配器二的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

STL经典案例(四)——实验室预约综合管理系统(项目涉及知识点很全面,内容有点多,耐心看完会有收获的!)

项目干货满满,内容有点过多,看起来可能会有点卡。系统提示读完超过俩小时,建议分多篇发布,我觉得分篇就不完整了,失去了这个项目的灵魂 一、需求分析 高校实验室预约管理系统包括三种不同身份:管理员、实验室教师、学生 管理员:给学生和实验室教师创建账号并分发 实验室教师:审核学生的预约申请 学生:申请使用实验室 高校实验室包括:超景深实验室(可容纳10人)、大数据实验室(可容纳20人)、物联网实验

C++ STL 适配器

系列文章目录 模板特例化,偏特化,左右值引用 https://blog.csdn.net/surfaceyan/article/details/126794013 C++ STL 关联容器 https://blog.csdn.net/surfaceyan/article/details/127414434 C++ STL 序列式容器(二) https://blog.csdn.net/surfac

【高等代数笔记】线性空间(一到四)

3. 线性空间 令 K n : = { ( a 1 , a 2 , . . . , a n ) ∣ a i ∈ K , i = 1 , 2 , . . . , n } \textbf{K}^{n}:=\{(a_{1},a_{2},...,a_{n})|a_{i}\in\textbf{K},i=1,2,...,n\} Kn:={(a1​,a2​,...,an​)∣ai​∈K,i=1,2,...,n

win7系统中C盘空间缩水的有效处理方法

一、深度剖析和完美解决   1、 休眠文件 hiberfil.sys :   该文件在C盘根目录为隐藏的系统文件,隐藏的这个hiberfil.sys文件大小正好和自己的物理内存是一致的,当你让电脑进入休眠状态时,Windows 7在关闭系统前将所有的内存内容写入Hiberfil.sys文件。   而后,当你重新打开电脑,操作系统使用Hiberfil.sys把所有信息放回内存,电脑

C++ STL关联容器Set与集合论入门

1. 简介 Set(集合)属于关联式容器,也是STL中最实用的容器,关联式容器依据特定的排序准则,自动为其元素排序。Set集合的底层使用一颗红黑树,其属于一种非线性的数据结构,每一次插入数据都会自动进行排序,注意,不是需要排序时再排序,而是每一次插入数据的时候其都会自动进行排序。因此,Set中的元素总是顺序的。 Set的性质有:数据自动进行排序且数据唯一,是一种集合元素,允许进行数学上的集合相

求空间直线与平面的交点

若直线不与平面平行,将存在交点。如下图所示,已知直线L过点m(m1,m2,m3),且方向向量为VL(v1,v2,v3),平面P过点n(n1,n2,n3),且法线方向向量为VP(vp1,vp2,vp3),求得直线与平面的交点O的坐标(x,y,z): 将直线方程写成参数方程形式,即有: x = m1+ v1 * t y = m2+ v2 * t

[Linux]:环境变量与进程地址空间

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:Linux学习 贝蒂的主页:Betty’s blog 1. 环境变量 1.1 概念 **环境变量(environment variables)**一般是指在操作系统中用来指定操作系统运行环境的一些参数,具有全局属性,可以被子继承继承下去。 如:我们在编写C/C++代码的时,在链接的时候,我们并不知

stl的sort和手写快排的运行效率哪个比较高?

STL的sort必然要比你自己写的快排要快,因为你自己手写一个这么复杂的sort,那就太闲了。STL的sort是尽量让复杂度维持在O(N log N)的,因此就有了各种的Hybrid sort algorithm。 题主你提到的先quicksort到一定深度之后就转为heapsort,这种是introsort。 每种STL实现使用的算法各有不同,GNU Standard C++ Lib

【编程底层原理】方法区、永久代和元空间之间的关系

Java虚拟机(JVM)中的内存布局经历了几个版本的变更,其中方法区、永久代和元空间是这些变更中的关键概念。以下是它们之间的关系: 一、方法区: 1、方法区是JVM规范中定义的一个概念,它用于存储类信息、常量、静态变量、即时编译器编译后的代码等数据。 3、它是JVM运行时数据区的一部分,与堆内存一样,是所有线程共享的内存区域。 二、永久代(PermGen): 1、在Java SE 7之前,

算法复杂度 —— 数据结构前言、算法效率、时间复杂度、空间复杂度、常见复杂度对比、复杂度算法题(旋转数组)

目录 一、数据结构前言 1、数据结构 2、算法 3、学习方法 二、 算法效率 引入概念:算法复杂度  三、时间复杂度 1、大O的渐进表示法 2、时间复杂度计算示例  四、空间复杂度 计算示例:空间复杂度 五、常见复杂度对比 六、复杂度算法题(旋转数组) 1、思路1 2、思路2 3、思路3 一、数据结构前言 1、数据结构         数据结构(D