本文写于2017-03-03,从老账号迁移到本账号,原文地址:https://www.cnblogs.com/huangweiyang/p/6440830.html

STL的六大组件:容器、算法、迭代器、空间配置器、容器适配器、仿函数。

空间配置器

空间配置器产生的缘由:由于程序需求,很多小块内存在程序中动态申请、释放。于是就容易出现内存外部碎片问题,同时由于一直调用malloc系统调用,产生性能问题。
(注:内碎片:因为内存对齐/访问效率而差生如用户需要3字节,实际得到4字节的问题,其中的碎片是浪费掉的。外碎片:系统内存总量足够,但是不连续,所以无法分配给用户使用而产生的浪费)。

实现策略:
用户申请空间大于128字节?大于就调用一级空间配置器,使用malloc分配内存。否则调用二级空间配置器,从内存池分配内存。一级空间配置器使用malloc/free,还增加了类似new_handler的malloc_handler机制。默认通过USE_MALLOC宏选择配置。

二级空间配置器也就是内存池,维护一个自由链表数组,类似于哈希桶,每个桶负责分配8,16,24,直到128,以8的倍数为内存分配单元,每个桶连接一个自由链表,将对应大小的内存块链接起来。分配内存的基本过程,用户申请内存,检查自由链表是挂有空闲节点,如果有直接取走。如果没有,自由链表向内存池申请节点。内存池如果有空间,直接去内存链接到链表,返回一个给用户。如果没有,需要使用malloc扩充内存池,扩充的大小是需求的两倍加上一个随配置次数增加愈来愈大的附加量。如果malloc也失败了,系统heap没有足够空间了,那么内存池就会四处寻找没有分配的且足够大的区块,找到了就分配给用户。找不到就主动调用第一级空间配置器,因为第一级空间配置器有out-of-memory处理机制,或许可以释放其他内存拿来此处使用如果可以就成功,否则发出bad_alloc异常。

vector

vector的数据安排与操作方式,与array非常相似。两者唯一区别在于空间的灵活运用性。array是静态空间,一旦配置就不能改变。vector是动态空间,可随时扩充空间容纳新元素。当然为了提高vector的效率,我们可以使用reserve()函数提前分配空间,这样push_back就不用频繁分配空间了。vector当旧空间满载时,如果要增加新的元素,不是在原有位置上持续更新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原来大小的两倍另外配置一块较大的空间,然后将原空间内容拷贝过来,再构造新元素,并释放原空间。因此,对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器都失效了。当进行删除操作(erase,pop_back)后,指向删除点的迭代器全部失效;指向删除点后面的元素的迭代器也将全部失效。vector内存空间由空间配置器分配,即使vector进行clear操作,这步分内存也不会释放掉。如果要释放掉vector的内存,可以使用临时变量+swap的方法。vector随机存储效率高,但插入元素效率低,因为要移动很多的数目,vector因此都不提供push_front()方法。

list

vector和数组类似,它拥有一段连续的内存空间,并且起始地址不变,很好的支持了随机存取,但由于是连续空间,所以在中间进行插入、删除等操作时都造成了内存块的拷贝和移动,另外在内存空间不足时还需要重新申请一大块内存的拷贝。为了克服这些缺陷,STL定义了另一种容器list,它对于数据插入和删除的时间复杂度均为O(1),,而且内存方面不用频繁的拷贝转移。

List是一个双向链表,所以迭代器是一个双端迭代器。在vector中如果进行插入和删除操作后迭代器会失效,list有一个重要的性质就是插入和接合操作都不会造成原有的迭代器失效。删除时仅有被删除节点迭代器失效。

STL在list最末尾节点和头结点之间插入一个头指针,它的prev指向尾节点,next指向头结点,仅凭一个指针就可以表现出整个list。

deque

vector支持随机访问,list支持高效删除,而deque支持随机访问以及首尾元素的高效删除。deque容器采用的是一种整体不连续,但是分段连续的存储空间,使用一个map数组即中控器来管理这些空间。deque的迭代器有四个属性组成,curr、first、last、node。curr指向真实元素,符合STL左开右闭。first和last是每个缓冲区已分配元素的左右边界。node指向中控器,用来实现连续空间已满时迭代器跳跃到另一片连续空间。deque容器有两个迭代器成员,start和finish,分别指向当前所用的第一个有效缓冲区和最后一个缓冲区。这就为deque的首尾增删操作提供了O(1)时间的复杂度。同时对于随机访问,通过调用start迭代器重载的[]实现,如果随机访问的元素在同一缓冲区,curr指针直接加上偏移量就可以访问。如果不在,通过连续缓冲区大小计算要跳跃到的缓冲区,然后跳到相应的偏移量即可访问。

使得deque容器失效的操作,在deque首部或尾部插入操作时,通常迭代器不会失效。插入端如果没有空间了,并不会直接分配空间。而是先判断另外一端是否有足够的空间(map_size>2*已使用的map个数),如果有,则只需调整map相应指针即可。如果没有,则进行申请空间、复制元素、删除旧空间的三部曲操作,这时迭代器才会失效。在deque中间做插入或删除时,STL会判断一下两边元素的数目,移动元素数目少的一边为插入元素挪出地方,所以元素少的一边迭代器会失效!

map

map是关联容器,以键值对的形式进行存储,方便进行查找。关键词起到索引的作用,表示与索引相关的数据。以红黑树的结构实现,插入删除等操作都在O(lgn)时间内完成。

set

set也是关联容器,set中每个元素只包含一个关键字。set支持高效的关键字查询操作--检查一个给定的关键字是否在set中。set也是红黑树实现,支持高效插入删除。

STL空间配置器、vector、list、deque、map复习的更多相关文章

  1. STL空间配置器那点事

    STL简介 STL(Standard Template Library,标准模板库),从根本上说,STL是一些“容器”的集合,这些“容器”有list,vector,set,map等,STL也是算法和其 ...

  2. 【陪你系列】5 千字长文+ 30 张图解 | 陪你手撕 STL 空间配置器源码

    大家好,我是小贺. 点赞再看,养成习惯 文章每周持续更新,可以微信搜索「herongwei」第一时间阅读和催更,本文 GitHub https://github.com/rongweihe/MoreT ...

  3. 咬碎STL空间配置器

    STL空间配置器 一.开场白: 给我的感觉就是,了解是空间配置器的功能,是那么的明了:在看原理,我还是很开心:接下来是360度大转变: 那么长的变量或者函数命名.那么多的宏.不爽,不过,遇上我这种二货 ...

  4. STL空间配置器

    1.什么是空间配置器? 空间配置器负责空间配置与管理.配置器是一个实现了动态空间配置.空间管理.空间释放的class template.以内存池方式实现小块内存管理分配.关于内存池概念可以点击:内存池 ...

  5. STL空间配置器解析和实现

    STL空间配置器的强大和借鉴作用不言而喻,查阅资料,发现了Dawn_sf已经对其有了极其深入和详细的描述,所以决定偷下懒借用其内容,只提供自己实现STL空间配置器的源码,具体解析内容参考:(一)STL ...

  6. stl空间配置器线程安全问题补充

    摘要 在上一篇博客<STL空间配置器那点事>简单介绍了空间配置器的基本实现 两级空间配置器处理,一级相关细节问题,同时简单描述了STL各组件之间的关系以及设计到的设计模式等. 在最后,又关 ...

  7. 【转】STL空间配置器

    STL空间配置器(allocator)在所有容器内部默默工作,负责空间的配置和回收.STL标准为空间配置器定义了标准接口(可见<STL源码剖析>P43).而具体实现细节则由各编译器实现版本 ...

  8. STL——空间配置器(构造和析构基本工具)

    以STL的运用角度而言,空间配置器是最不需要介绍的东西,它总是隐藏在一切组件(更具体地说是指容器,container)的背后,默默工作,默默付出.但若以STL的实现角度而言,第一个需要介绍的就是空间配 ...

  9. STL——空间配置器(SGI-STL)

    一. 空间配置器标准接口 参见<STL源码剖析>第二章-2.1.<memory>文件. 二.具备次配置力的SGI空间配置器 1. SGI STL的配置器与众不同,也与标准规范不 ...

随机推荐

  1. autoit脚本-从基本的函数用法开始

    适配浏览器:目前了解的有ie浏览器 MsgBox 显示可选提示超时的消息框 _ArrayDisplay _arraydisplay($aArray)  ;$aArra一般为数组,方法用于展示表格展示数 ...

  2. JS(JavaScript)的进一步了解7(更新中···)

    1.Js操作css样式 div.style.width=”100px”.在div标签内我们添加了一个style属性,并设定 了width值.这种写法会给标签带来大量的style属性,跟实际项目是不符. ...

  3. code回顾

    Linq return Content("<script>alert('你想说的话');javascript:history.go(-1);</script>&quo ...

  4. JS高程关于ajax的学习笔记

    1.ajax介绍 ajax技术可以实现浏览器向服务器请求数据时不需要重新加载页面,就可以从服务器中获取需要的数据. ajax技术的核心是XMLHttpRequest对象(简称XHR),XHR对象为向服 ...

  5. CF Round #551 (Div. 2) D

    CF Round #551 (Div. 2) D 链接 https://codeforces.com/contest/1153/problem/D 思路 不考虑赋值和贪心,考虑排名. 设\(dp_i\ ...

  6. MySQL之 视图,触发器,存储过程,函数,事物,数据库锁,数据库备份

    1.视图 视图: 是一个虚拟表,其内容由查询定义: 视图有如下特点;  1. 视图的列可以来自不同的表,是表的抽象和逻辑意义上建立的新关系.  2. 视图是由基本表(实表)产生的表(虚表).  3. ...

  7. JavaScript形而上的For循环中的Break

    break相当于循环中的GOTO,需避免使用. 下面是一个break使用例子. 找出第一个months小于7的项目. const cats = [ { name: 'Mojo', months: 84 ...

  8. leetcode02大数相加

    惭愧惭愧,这道题居然卡了两天,犯了一堆错误,现在一一总结 错误 头一天我看给的测试用例误以为输入是数组,做了半天也无法输出链表的正确格式,后来把输入当成链表,才正确了 我没看到编辑器给了一套链表,自己 ...

  9. 2019金融科技风往哪儿吹?蚂蚁金服联合20余家金融机构预测新年热点:5G、区块链上榜

    2019年,金融科技的风向标在哪里?哪些板块成新宠,哪些科技成潮流? 1月4日,蚂蚁金服ATEC城市峰会在上海举行.大会上,蚂蚁金服与20余家金融机构一起预测了2019年金融科技的发展. “未来金融会 ...

  10. HashMap循环过程中删除元素发生ConcurrentModificationException的源码分析