《STL源码剖析》笔记——allocator
创始人
2024-02-06 16:03:27
0

六大组件间关系

在这里插入图片描述

部分STL文件包含关系

在这里插入图片描述
allocator包含于中:
实际实现于三个文件 :
1.stl_construct.h :对象的构造和析构
2.stl_alloc.h空间配置和释放
3.stl_uninitialized.h

空间配置器(allocator)

1.什么是空间配置器?
为容器取得数据存储空间的类template从用户代码std::vector v;开始,vector的模板参数class T被替换为int,同时第二个模板参数因为没有指定,所以为默认模板参数,即allocator,这个vector对象v会在内部实例一个allocator的对象,用来管理内存。

2.空间配置器需要哪些功能?
负责空间配置与管理,从实现了动态空间配置、空间管理、空间释放的class template

空间配置器(allocator)标准接口

//traits 编程技法可以暂时不了解
allocator::value_type
allocator::pointer
allocator::const_pointer
allocator::reference
allocator::const_reference
allocator::size_type
allocator::difference// 一个嵌套的(nested)class template,class rebind拥有唯一成员other,那是一个typedef,代表allocator
allocator::rebindallocator::allocator() // 默认构造函数
allocator::allocator(const allocator&) // 拷贝构造函数
template allocator::allocator(const allocator&) // 泛化的拷贝构造函数
allocator::~allocator() // 析构函数// 返回某个对象的地址,a.address(x)等同于&x
pointer allocator::address(reference x) const
// 返回某个const对象的地址,a.address(x)等同于&x
const_pointer allocator::address(const_reference x) const// 配置空间,足以存储n个T对象。第二个参数是个提示。实现上可能会利用它来增进区域性(locality),或完全忽略之
pointer allocator::allocate(size_type n, const void* = 0)
// 释放先前配置的空间
void allocator::deallocate(pointer p, size_type n)// 返回可成功配置的最大量
size_type allocator:maxsize() const// 调用对象的构造函数,等同于 new((void*)p) T(x)
void allocator::construct(pointer p, const T& x)
// 调用对象的析构函数,等同于 p->~T()
void allocator::destroy(pointer p)

一个最简单的allocator就可以理解为对new,delete的简单封装,以及对构造函数和析构函数的直接调用。

书中实现

#ifndef _MYALLOC_
#define _MYALLOC_#include 
#include 
#include 
#include 
#include namespace my_alloc
{// allocate的实际实现,简单封装new,当无法获得内存时,报错并退出template inline T* _allocate(ptrdiff_t size, T*) {set_new_handler(0);T* tmp = (T*)(::operator new((size_t)(size * sizeof(T))));if (tmp == 0) {cerr << "out of memory" << endl;exit(1);}return tmp;}// deallocate的实际实现,简单封装deletetemplate inline void _deallocate(T* buffer) { ::operator delete(buffer); }// construct的实际实现,直接调用对象的构造函数template inline void _construct(T1* p, const T2& value) { new(p) T1(value); }// destroy的实际实现,直接调用对象的析构函数template inline void _destroy(T* ptr) { ptr->~T(); }template class allocator {public:typedef T           value_type;typedef T*          pointer;typedef const T*    const_pointer;typedef T&          reference;typedef const T&    const_reference;typedef size_t      size_type;typedef ptrdiff_t   difference_type;// 构造函数allocator(){ return; }template allocator(const allocator& c){}// rebind allocator of type Utemplate struct rebind { typedef allocator other; };// allocate,deallocate,construct和destroy函数均调用上面的实际实现// hint used for locality. ref.[Austern],p189pointer allocate(size_type n, const void* hint = 0) {return _allocate((difference_type)n, (pointer)0);}void deallocate(pointer p, size_type n) { _deallocate(p); }void construct(pointer p, const T& value) { _construct(p, value); }void destroy(pointer p) { _destroy(p); }pointer address(reference x) { return (pointer)&x; }const_pointer const_address(const_reference x) { return (const_pointer)&x; }size_type max_size() const { return size_type(UINT_MAX / sizeof(T)); }   };
} // end of namespace myalloc

自己编写的allocator为vector分配空间

#include 
int main()
{std::vector > v;// Do something;return 0;
}

该实现符合STL标准,但是通过不了GCC编译器,原因是SGI STL的allocator并不完全符合STL规范。在gcc9.2.0(mingw-w64 on msys2)里,上面这个“最简单的allocator实现”微小改动(给set_new_handler、cerr、endl三处加上std::)以后是可以编译通过。
在这里插入图片描述

SGI STL 默认配置器:std::alloc 详解

上面实现的满足STL标准的allocator只是简单的实现内存配置/释放,即对new和delete的浅包装,SGI中拥有其独特的操作来优化alloc的性能

alloc总体架构

1.构造和析构基本工具construct()destory
2.空间的配置与释放工具 一级配置器、二级配置器
3.调用系统内存函数

在这里插入图片描述

new操作

class Foo{....}
Foo *pf =new Foo;
delete pf

上述代码new操作主要分为两个阶段的操作
1.调用::operator new 配置内存
2.调用构造函数 Foo()构造对象内容
delete也包含两个操作:
1.调用Foo:~Foo()将对象析构
2.调用::operator delete 释放内存

STL 中 内存配置操作由 alloc:allocate 负责
内存释放由alloc::deallocate负责,对象构造由::construct 负责,对象析构由
::destroy负责

destroy

直接使用模板编程调用析构函数

template
inline void destroy(T *pointer)
{pointer->~T();
}

construct

template
inline void construct (T1*p,const T2& value)
{new(p) T1(value);
}

在SGI源码中加入了第二版destroy,主要根据trivial来特化实例
在这里插入图片描述

allocate

在SGI中,alloc优化了申请内存和释放的性能。拿vector来举例,申请一个vector时,我们调用alloc为其申请内存空间。
在这里插入图片描述
在SGI中将alloc分为一级适配器和二级适配器,以应用于内存大小不同的场景。大于128bytes直接调用一级alloc,小于则使用二级alloc。二级适配器采用维护16个自由链表来分配内存,这主要是为了解决小型区块可能造成的内存碎片问题。
在这里插入图片描述

空间释放函数deallocate

该函数首先会判断区块大小,大于128bytes调用一级配置器,小于128bytes就找到对应的自由链表,将区块回收

另外的内存处理工具

STL 定义了5个全局函数,作用容器配置空间。
1.构造函数 construct
2.析构函数 destroy
3.uninitialized_copy ->copy()
4.uninitialized_fill->fill()
5.uninitialized_fill_n->filln()
在这里插入图片描述

总结

本文简单介绍了STL组件之一空间配置器,先从标准接口来简要的理解allocator的功能紧接着用templet编程写了一个简单的allocator,然后记录了SGI 中利用traits编程技法来特化提高函数效率,包括一二级适配器优化内存管理的过程,最后介绍了另外几个内存全局函数。本篇文章并未具体细节代码进行讲解是对《STL源码剖析》框架上的总结,若读者对具体代码有兴趣,可以直接读原书。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...