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

相关文章

MySQL启动报错:InnoDB表空间丢失问题及解决方法

《MySQL启动报错:InnoDB表空间丢失问题及解决方法》在启动MySQL时,遇到了InnoDB:Tablespace5975wasnotfound,该错误表明MySQL在启动过程中无法找到指定的s... 目录mysql 启动报错:InnoDB 表空间丢失问题及解决方法错误分析解决方案1. 启用 inno

在Java中基于Geotools对PostGIS数据库的空间查询实践教程

《在Java中基于Geotools对PostGIS数据库的空间查询实践教程》本文将深入探讨这一实践,从连接配置到复杂空间查询操作,包括点查询、区域范围查询以及空间关系判断等,全方位展示如何在Java环... 目录前言一、相关技术背景介绍1、评价对象AOI2、数据处理流程二、对AOI空间范围查询实践1、空间查

MySQL表空间结构详解表空间到段页操作

《MySQL表空间结构详解表空间到段页操作》在MySQL架构和存储引擎专题中介绍了使用不同存储引擎创建表时生成的表空间数据文件,在本章节主要介绍使用InnoDB存储引擎创建表时生成的表空间数据文件,对... 目录️‍一、什么是表空间结构1.1 表空间与表空间文件的关系是什么?️‍二、用户数据在表空间中是怎么

CentOS7增加Swap空间的两种方法

《CentOS7增加Swap空间的两种方法》当服务器物理内存不足时,增加Swap空间可以作为虚拟内存使用,帮助系统处理内存压力,本文给大家介绍了CentOS7增加Swap空间的两种方法:创建新的Swa... 目录在Centos 7上增加Swap空间的方法方法一:创建新的Swap文件(推荐)方法二:调整Sww

查看Oracle数据库中UNDO表空间的使用情况(最新推荐)

《查看Oracle数据库中UNDO表空间的使用情况(最新推荐)》Oracle数据库中查看UNDO表空间使用情况的4种方法:DBA_TABLESPACES和DBA_DATA_FILES提供基本信息,V$... 目录1. 通过 DBjavascriptA_TABLESPACES 和 DBA_DATA_FILES

Linux环境变量&&进程地址空间详解

《Linux环境变量&&进程地址空间详解》本文介绍了Linux环境变量、命令行参数、进程地址空间以及Linux内核进程调度队列的相关知识,环境变量是系统运行环境的参数,命令行参数用于传递给程序的参数,... 目录一、初步认识环境变量1.1常见的环境变量1.2环境变量的基本概念二、命令行参数2.1通过命令编程

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把所有信息放回内存,电脑