IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【c++从菜鸡到王者】第七篇:STL-空间配置器 -> 正文阅读

[C++知识库]【c++从菜鸡到王者】第七篇:STL-空间配置器

空间配置器

详解SGI特殊的空间配置器-alloc

  • 我们所习惯的c++内存操作:new/delete (new: 首先operator new 配置内存,再然后 调用构造函数构造对象;delete:先调用析构函数析构对象,在operate delete 释放内存)

    • STL决定将上面的两个过程分开,内存配置操作由alloc::allocate()完成,释放由alloc::deallocate().对象构造由::construct()完成,对象析构由destroy()完成。在STL中,配置器定义在< memery >中,里面包含三个头文件<stl_construct.h>(这里定义了全局函数construct()与destroy(),负责对象的构造与析构)<stl_alloc.h>(这里定义了一,二级配置器,彼此合作,后面解释什么是一二级配置器),<stl_uninitialized.h>(这里面定义了一些全局函数,用来填充或复制大块内存数据:un_initialized_copy(),un_initialized_fill(),un_unitialized_fill_n())
  • 构造与析构函数基本工具:construct(),destroy() ; construct,接受一个指针与初值value,意为将初值设定到指针所指的空间上。;destroy()有两个版本,第一个接受一个指针,将指针所指之物析构掉,进而直接调用析构函数。第二个版本是接受一对迭代器,指向一段范围的空间,我们不清楚这个范围有多大,如果我们重复的调用析构函数,这将给效率造成负担。所以我们应该首先应该根据value_type()去判断这个对象的类别,再根据(使用_type_traits< T >判断)这个类别取判断该类别的析构函数是否无关痛痒。如果这些析构函数无关痛痒,那么就什么也不做,否则就一次次的重复调用析构函数。【这里的_type_traits< T >是STL的编程技法。具体分析看我前面的文章解释,后面我也会详细的解析】

  • 空间的配置与释放:为了解决小型区域可能造成的碎片问题,我们设置双层级配置器,第一级配置器,直接调用malloc()与free().第二季配置根据情况采用不同策略:当配置区过大(超过128bytes),我们就调用一级配置器,当配置区过小,为了降低负担,我们便采用memory pool 的整理方式,进而不采用第一级配置器。```SGI STL还为alloc包装了一个接口,让它的配置单位从bytes到元素的大小

    template<class T,class Alloc>
    class simple_alloc{
        static T *allocate(size_t n){
            return 0==n?0:(T*)Alloc::allocate(n*sizeof(T));
        }
        static T*allocate(void){
            return (T*)Alloc::allocate(n*sizeof(T));
        }
        static void deallocate(T *p,size_t n){
            if(0!=n)
                Alloc::deallocate(p,n*sizeof(T));
        }
        static void deallocate(T *p){
            Alloc::deallocate(p,sizeof(T));
        }
        
    };
    //下面使vector调用alloc的过程
    template<class T,class Alloc=alloc>
    class vector{
        typedef simple_alloc<value_type,Alloc>data_allocator;
            void deallocate(){
            if(...)
                data_allocator::deallocate(...);
        }
    };
    
  • 第一级配置器剖析

    • 第一级配置器以malloc(),free(),remalloc()等c函数来进行内存的配置,释放,重配置。并实现出c++new handler的行为
    • c++new handler机制:你可以要求系统在内存需要配置不被满足的时候,调用你所指定的一个函数。,也就是一旦operator new 无法完成时,会在抛出std::bad_allc之前,先调用由客端指定的例程,该例程用来解决内存不足的问题【"内存不足处理例程"使客端的责任,如果,未设定,那么就会直接抛异常信息
    • 一级配置器,在调用malloc(),与remalloc()不成功之后就会直接调用oom_malloc(),与oom_remalloc(),他们中有内循环,可以反复调用内存不足处理例程。以达到内存配置的目的,如果客端未设置例程那么,就会oom_malloc(),与oom_remalloc()就会抛出异常信息
  • 第二级配置器剖析

    • 二级配置级做法:如果所需区块过大,那么就交给第一级配置器处理,如果小于128bytes,则以内存池管理:每次配置一大块内存,并维护对应之自由链表。下次如果有相同大小的内存需求就直接拨出。如果客端还小额区块,就有配置器回收至自由链表中(free-lists),同时STL第二季配置器还会主动将内存需求量上升至8的倍数。

    • 空间配置函数:身为第二级配置器,其含有allocate()函数,该函数首先判断区块大小,如果大于128bytes就调用第一级配置器,如果小于就寻找16个free_lists中的一个,如果没找到可用的区块,就会将区块大小上升至8的倍数,然后调用refill()函数为free-list填充空间

    • 空间释放函数,该函数首先判断区块大小,如果大于128bytes就调用第一级配置器,如果小于,就寻找对应的free-lists,将区块回收。

  • 内存池

    • 内存池(Memory Pool)是一种动态内存分配与管理技术,通常情况下,程序员习惯直接使用new,delete,malloc,free等API申请和释放内存,这样导致的后果就是:当程序运行的时间很长的时候,由于所申请的内存块的大小不定,频繁使用时会造成大量的内存碎片从而降低程序和操作系统的性能。

    • 内存池则是在真正使用内存之前,先申请分配一大块内存(内存池)留作备用。当程序员申请内存时,从池中取出一块动态分配,当程序员释放时,将释放的内存放回到池内,再次申请,就可以从池里取出来使用,并尽量与周边的空闲内存块合并。若内存池不够时,则自动扩大内存池,从操作系统中申请更大的内存池。

    • 内存池的实现(一) - bangerlee - 博客园 (cnblogs.com)

    • 内存池的实现(二) - bangerlee - 博客园 (cnblogs.com)

      以上是两篇写的比较好的博客,深度剖析了内存池

  • 内存基本处理工具(5个函数)

    • uninitialized_copy() :

      template<class InputIterator,class ForwardIterator>
      ForwardIterator
      uninitialized_copy(InputIterator first,InputIterator last,ForwardIterator result)
      //result这个范围迭代器,指向一片未初始化的区域。uninitialized_copy()会调用construct函数将输入范围里的所有元素产生一份复制品放入输出范围中对应位置上。
      //c++标准要求uninitialized_copy() 要么构造出所有的元素,要么什么也不构造,最适合用来实现一个容器。
      
    • uninitialized_fill()

      template<class ForwardIterator,class T>
      void uninitialized_fill(InputIterator first,InputIterator last,const T&x)
      //[firsst,last)指的是一片未初始化的区域,对于这个区域,这个函数会对于这个操作范围内的所有迭代器i,使用construct(&*i,x),在i所指之处产生x的复制品
      //c++标准要求这个函数要么产生出所有的元素,要么什么也不要产生。
      
    • uninitialized_fill_n()

      template<class ForwardIterator,class Size,class T>
      ForwardIterator
      uninitialized_fill_n(ForwardIterator first,Size n,const T&x)
      //在【first,first+n)这个范围内构造x的复制品,与上面的函数实现一样
      

      另外两个函数上面已经介绍分别是construct(),与destroy().同时上面3个unin型函数会在底层调用更高级的函数:copy(),fill(),fill_n();

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-26 11:53:50  更:2021-07-26 11:55:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年3日历 -2024/3/28 20:06:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码