STL源码剖析——空间配置器Allocator#1 构造与析构
以STL的运用角度而言,空间配置器是最不需要介绍的东西,因为它扮演的是幕后的角色,隐藏在一切容器的背后默默工作。但以STL的实现角度而言,最应该首先介绍的就是空间配置器,因为这是这是容器展开一切运作的基石。空间配置器顾名思义就是配置空间的器件,为存放在容器里的信息找到安家落户的地方(内存)。
SGI STL上有两个空间配置器,一个是std::allocator,一个是std::alloc,前者只是单纯的把基层的内存配置/释放行为(::operator new 和 ::operator delete)做了一层简单的封装,不作总结;后者才是我们应该重点学习的对象。
一般而言,C++的内存配置与释放操作是这样的:
class Foo {...};
Foo* pf = new Foo;
delete pf;
其中的new包含两阶段的操作:(1)调用::operator new分配内存;(2)调用Foo::Foo()构造对象内容。delete也包含两阶段的操作:(1)调用Foo::~Foo()将对象析构;(2)调用::operator delete释放内存。。
而在std::alloc中同理,内存配置操作由alloc::allocate()负责,释放由alloc::deallocate()负责;对象构造操作由::construct()负责,析构由::destroy()负责。而这两组函数分别在两个头文件里,而这两个头文件又被<memory>所包含:
- #include<stl_alloc.h> //负责内存空间的配置与释放
- #incluce<stl_construct.h> //负责对象内容的构造与析构

从这幅图中能大致看出空间配置器的概貌,本文先就从<stl_construct.h>出发学习空间配置器中对象的构造与析构。
//<stl_construct.h>的部分内容 #include <new.h> // 欲使用 placement new,需先含包含此文件 template <class T1, class T2>
inline void construct(T1* p, const T2& value) {
new (p) T1(value); // placement new; 喚起T1::T1(value);
} /*new (p) T1(value); 是指在p所指的内存上调用T1的构造函数,把其产生的对象存放在p所指内存里。而T1::T1(value);说明T1构造函数的形参为const T2 &(一个T2类型的常引用变量)。*/ // 以下是 destroy() 第一版本,接受一個指標。
template <class T>
inline void destroy(T* pointer) {
pointer->~T(); // 喚起 dtor ~T()
} // 以下是 destroy() 第二版本,接受兩個迭代器。此函式是設法找出元素的數值型別,
// 進而利用 __type_traits<> 求取最適當措施。
template <class ForwardIterator>
inline void destroy(ForwardIterator first, ForwardIterator last) {
__destroy(first, last, value_type(first));
} // 判斷元素的數值型別(value 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());
} // 如果元素的數值型別(value type)有 non-trivial destructor…
template <class ForwardIterator>
inline void
__destroy_aux(ForwardIterator first, ForwardIterator last, __false_type) {
for ( ; first < last; ++first)
destroy(&*first);
} // 如果元素的數值型別(value type)有 trivial destructor…
template <class ForwardIterator>
inline void __destroy_aux(ForwardIterator, ForwardIterator, __true_type) {} // 以下是destroy() 第二版本針對迭代器為 char* 和 wchar_t* 的特化版
inline void destroy(char*, char*) {}
inline void destroy(wchar_t*, wchar_t*) {}

construct()接受一个指针p和一个初值value,该函数的作用就是将value作为实参在指针所指的空间上调用构造函数产生对象。关于placement new相关知识可以浏览这篇博客。
destroy()有两个版本,第一个版本很简单,直接调用该对象的析构函数即可。而第二个版本就稍微复杂点,要把[first, last)范围内的所有对象析构掉,这里涉及到一个问题,如果范围很大,但对每个对象的析构函数都无关痛痒,那么一次次调用这些无关痛痒的析构函数会造成性能上的损失。因此,这里首先利用value_type()获得迭代器所指对象的类型,再利用__type_traits<T>判断该类型的析构函数是否无关痛痒。若是(__true_type),则什么也不做;若否(__false_type),这才以循环的方式遍历整个区间范围,并逐一调用每一个对象上析构函数。而对于如何实现获得迭代器所指之物的类型和如何实现判断析构函数是否无关痛痒将在学习trait编程时有所提及。
STL源码剖析——空间配置器Allocator#1 构造与析构的更多相关文章
- STL源码剖析 — 空间配置器(allocator)
前言 以STL的实现角度而言,第一个需要介绍的就是空间配置器,因为整个STL的操作对象都存放在容器之中. 你完全可以实现一个直接向硬件存取空间的allocator. 下面介绍的是SGI STL提供的配 ...
- STL源码剖析——空间配置器Allocator#2 一/二级空间配置器
上节学习了内存配置后的对象构造行为和内存释放前的对象析构行为,在这一节来学习内存的配置与释放. C++的内存配置基本操作是::operator new(),而释放基本操作是::operator del ...
- STL源码剖析——空间配置器Allocator#3 自由链表与内存池
上节在学习第二级配置器时了解了第二级配置器通过内存池与自由链表来处理小区块内存的申请.但只是对其概念进行点到为止的认识,并未深入探究.这节就来学习一下自由链表的填充和内存池的内存分配机制. refil ...
- STL源码剖析(空间配置器)
前言 在STL中,容器的定义中都带一个模板参数,如vector template <class T, class Alloc = alloc> class vector {...} 其中第 ...
- STL源码剖析:配置器
作用:对内存的管理 接口:申请和释放 内容: 几个全局函数 一级配置器 二级配置器 准备知识 POD是什么: Plain Old Data简称POD,表示传统的C语言类型:与POD类型对应的是非POD ...
- STL学习笔记:空间配置器allocator
allocator必要接口: allocator::value_type allocator::pointer allocator::const_pointer allocator::referenc ...
- 《STL源码剖析》相关面试题总结
原文链接:http://www.cnblogs.com/raichen/p/5817158.html 一.STL简介 STL提供六大组件,彼此可以组合套用: 容器容器就是各种数据结构,我就不多说,看看 ...
- 面试题总结(三)、《STL源码剖析》相关面试题总结
声明:本文主要探讨与STL实现相关的面试题,主要参考侯捷的<STL源码剖析>,每一个知识点讨论力求简洁,便于记忆,但讨论深度有限,如要深入研究可点击参考链接,希望对正在找工作的同学有点帮助 ...
- STL源码剖析之空间配置器
本文大致对STL中的空间配置器进行一个简单的讲解,由于只是一篇博客类型的文章,无法将源码表现到面面俱到,所以真正感兴趣的码农们可以从源码中或者<STL源码剖析>仔细了解一下. 1,为什么S ...
随机推荐
- 如何把ANSYS模型输出为CDB文件并导入FLUENT 【转载】
转载自: http://linziok99.blog.163.com/blog/static/100157302009320134826/ 在main menu中选择Archive Model ,再点 ...
- elasticsearch type类型创建时注意项目,最新的elasticsearch已经不建议一个索引下多个type
https://www.elastic.co/guide/cn/elasticsearch/guide/current/mapping.html如果有两个不同的类型,每个类型都有同名的字段,但映射不同 ...
- Linux系统配置静态ip
一.工具/原料 redhat6.2 二.步骤 1."网络适配器"选择"桥接模式" 右键虚拟机,选择"设置"->"网络适配器& ...
- C仿黑白棋版XO棋
两位玩家轮流在棋盘上放置不同颜色的棋子,一位玩家使用黑子,另一位使用白子,棋盘是一个偶数正方形. 只能将一个棋子放在对手的棋子旁边,使对手在水平.垂直.对角线方向上的棋子变成自己的棋子,游戏结束时,棋 ...
- linux: QT安装时出现段错误segmentation fault
环境:macOS 10.14.6 VMware Fusion版本:11.0.1 QT版本:qt-creator-linux-x86_64-opensource-2.5.2.bin 安装时出现:segm ...
- vim脚本判断操作系统
Linux 和 Windows 通用配置 其实在配置文件中是可以通过逻辑代码判断平台做条件处理的,这样就可以实现一个配置文件两个个平台下共用了,判断逻辑如下: " ============= ...
- mongodb的开机自启动
一.背景 Linux轻松的在rc.local中写上启动脚本,reboot~发现没有启动成功.这不科学啊,查看日志发现“permission denied” 二.解决 Linux系统下,使用自定配置文件 ...
- openresty开发系列27--openresty中封装redis操作
openresty开发系列27--openresty中封装redis操作 在关于web+lua+openresty开发中,项目中会大量操作redis, 重复创建连接-->数据操作-->关闭 ...
- Java 并发基础常见面试题总结
1. 什么是线程和进程? 1.1. 何为进程? 进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的.系统运行一个程序即是一个进程从创建,运行到消亡的过程. 在 Java 中,当我们启 ...
- time zone list
GMT UTC WET WET CET CET MET CET ECT CET EET EET MIT Pacific/Apia HST Pacific/Honolulu AST America/An ...