文章目录
📊什么是空间配置器✈STL 提供六大组件的了解👀为什么需要空间配置器👍SGI-STL空间配置器实现原理🌂一级空间配置器的实现
📊什么是空间配置器
空间配置器,顾名思义就是为各个容器高效的管理空间(空间的申请与回收)的,在默默地工作。
✈STL 提供六大组件的了解
容器(containers):各种数据结构,如 vector, list, deque, set, map 用来存放数据。从实现的角度来看,STL 容器是一种 class template。算法(algorithms):各种常用的算法如 sort, search, copy, erase…从实现角度来看,STL 算法是一种 function template。迭代器(iterators):扮演容器与算法之间的胶合剂,是所谓的“泛型指针”。从实现角度来看,迭代器是一种将 operator *, operator ->, operator++, operator– 等指针相关操作予以重载的class template。仿函数(functors):行为类似函数,可以作为算法的某种策略。从实现角度来看,仿函数是一种重载了 operator() 的 class 或class template。适配器(adapters):一种用来修饰容器或仿函数或迭代器接口的东西。例如 STL 提供的 queue 和 stack,虽然看似容器,其实只能算是一种容器适配器,因为它们的底部完全借助 deque,所有操作都由底层的 deque 供应。配置器(allocator):负责空间配置与管理,从实现角度来看,配置器是一个实现了动态空间配置、空间管理、空间释放的 class template。👀为什么需要空间配置器
从使用 STL 层面而言,空间配置器并不需要介绍 ,因为容器底层都给你包装好了,但若是从 STL 实现角度出发,空间配置器是首要理解的。
作为 STL 设计背后的支撑,空间配置器总是在默默地付出着。为什么你可以使用算法来高效地处理数据,为什么你可以对容器进行各种操作,为什么你用迭代器可以遍历空间,这一切的一切,都有“空间配置器”的功劳。
模拟实现vector、list、map、unordered_map等容器时,所有需要空间的地方都是通过new申请的,虽然代码可以正常运行,但是有以下不足之处:
空间申请与释放需要用户自己管理,容易造成内存泄漏。频繁向系统申请小块内存块,容易造成内存碎片。频繁向系统申请小块内存,影响程序运行效率。直接使用malloc与new进行申请,每块空间前有额外空间浪费。申请空间失败怎么应对。代码结构比较混乱,代码复用率不高。未考虑线程安全问题。因此需要设计一块高效的内存管理机制。
👍SGI-STL空间配置器实现原理
以上提到的几点不足之处,最主要还是:频繁向系统申请小块内存造成的。那什么才算是小块内存?SGI-STL以128作为小块内存与大块内存的分界线,将空间配置器其分为两级结构,一级空间配置器处理大块内存,二级空间配置器处理小块内存。
🌂一级空间配置器的实现
一级空间配置器原理非常简单,直接对malloc与free进行了封装,并增加了C++中set_new_handle思想。
实现代码:
template <int inst>class __malloc_alloc_template{private: static void *oom_malloc(size_t);public:// 对malloc的封装 static void * allocate(size_t n) { // 申请空间成功,直接返回,失败交由oom_malloc处理 void *result = malloc(n); if (0 == result) result = oom_malloc(n); return result; }// 对free的封装 static void deallocate(void *p, size_t /* n */) { free(p);} // 模拟set_new_handle // 该函数的参数为函数指针,返回值类型也为函数指针 // void (* set_malloc_handler( void (*f)() ) )() static void (* set_malloc_handler(void (*f)()))() { void (* old)() = __malloc_alloc_oom_handler; __malloc_alloc_oom_handler = f; return(old); }};// malloc申请空间失败时代用该函数template <int inst>void * __malloc_alloc_template<inst>::oom_malloc(size_t n){void (* my_malloc_handler)();void *result;for (;;) { // 检测用户是否设置空间不足应对措施,如果没有设置,抛异常,模式new的方式 my_malloc_handler = __malloc_alloc_oom_handler; if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; } // 如果设置,执行用户提供的空间不足应对措施 (*my_malloc_handler)(); // 继续申请空间,可能就会申请成功 result = malloc(n); if (result) return(result);}}typedef __malloc_alloc_template<0> malloc_alloc;