上篇文章介绍了内存分配器allocator的设计,此篇介绍内存分配器的属性。

__alloc_traits类

1,__alloc_traits类提供了一个顶层内存分配器的萃取器,可以使用_Alloc的allocate, dellocate, construct, destory等函数来完成内存分配、释放,对象构造、析构等任务。
2,其中特例化版本为allocator,是STL容器默认的内存分配器。
3,如果想将自定义的内存分配器融入到STL体系中,需要像allocator一样完成相应的接口设计,以及rebind函数,容器可通过模板赋值使用自定义的内存分配器。

__alloc_traits定义内存分配器中allocator_type,_Base_type,value_type,pointer,const_pointer,const_pointer,size_type,difference_type,reference,const_reference等类型定义,以及rebind<_Tp>重绑定模板类,construct, destory内存分配、释放模板函数,allocate, dellocate对象构造、析构函数,以及max_size函数。

namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{template<typename _Alloc, typename = typename _Alloc::value_type>struct __alloc_traits //模板类 __alloc_traits: std::allocator_traits<_Alloc> //继承自allocator_traits,下面介绍{ //类型定义typedef _Alloc allocator_type; //内存分配器typedef std::allocator_traits<_Alloc>           _Base_type; //继承基类typedef typename _Base_type::value_type         value_type; //元素类型typedef typename _Base_type::pointer            pointer; //指针类型typedef typename _Base_type::const_pointer      const_pointer;typedef typename _Base_type::size_type          size_type;typedef typename _Base_type::difference_type    difference_type; //元素之间的距离typedef value_type&                             reference; //左值引用类型typedef const value_type&                       const_reference;using _Base_type::allocate; //基类所有allocate重载函数在声明点处可见using _Base_type::deallocate; //基类deallocate重载函数在声明点处可见using _Base_type::construct; //基类construct重载函数在声明点处可见using _Base_type::destroy; //基类destroy重载函数在声明点处可见using _Base_type::max_size; //基类max_size重载函数在声明点处可见private: //_Ptr与pointer类型相同,且不是标准类型指针时,__is_custom_pointer为truetemplate<typename _Ptr> //_Ptr是指向元素的自定义指针时为trueusing __is_custom_pointer= std::__and_<std::is_same<pointer, _Ptr>, //指针类型是否相同std::__not_<std::is_pointer<_Ptr>>>; //是否为标准类型指针public: //重载非标准类型指针的构造函数,标准指针会直接调用_Base_type的构造函数和析构函数template<typename _Ptr, typename... _Args> //构造函数模板,模板参数为指针和构造类型所需参数static typename std::enable_if<__is_custom_pointer<_Ptr>::value>::type //返回为_Ptr或pointerconstruct(_Alloc& __a, _Ptr __p, _Args&&... __args){ //调用基类构造函数construct_Base_type::construct(__a, std::__to_address(__p),std::forward<_Args>(__args)...);}template<typename _Ptr> //重载非标准类型指针的析构函数static typename std::enable_if<__is_custom_pointer<_Ptr>::value>::typedestroy(_Alloc& __a, _Ptr __p){ _Base_type::destroy(__a, std::__to_address(__p)); }//判断内存分配器是否包含拷贝、移动构造函数,交换及比较相等操作//内存分配器中如果有相应成员函数则定义相应成员为true_type或false_type//true_type::value为true,false_type::value为falsestatic constexpr bool _S_propagate_on_copy_assign(){ return _Base_type::propagate_on_container_copy_assignment::value; }static constexpr bool _S_propagate_on_move_assign(){ return _Base_type::propagate_on_container_move_assignment::value; }static constexpr bool _S_propagate_on_swap(){ return _Base_type::propagate_on_container_swap::value; }static constexpr bool _S_always_equal(){ return _Base_type::is_always_equal::value; }static constexpr bool _S_nothrow_move(){ return _S_propagate_on_move_assign() || _S_always_equal(); }template<typename _Tp>struct rebind //基类rebind_alloc<_Tp>等于_Alloc<_Tp>,封装基类rebind定义_Alloc<_Tp>别名为other{ typedef typename _Base_type::template rebind_alloc<_Tp> other; };};
} // namespace __gnu_cxx

模板类allocator_traits类和__allocator_traits_base,获取内存分配器Alloc的属性,内存分配器不一定是std::allocator,可以是自定义的。

以及内存分配器std::allocator的属性萃取

namespace std _GLIBCXX_VISIBILITY(default)
{struct __allocator_traits_base{ //_Tp没有rebind成员函数时,调用此版本__rebind,成员type类型为_Tp<_Up>template<typename _Tp, typename _Up, typename = void> //类模板,继承自__replace_first_argstruct __rebind : __replace_first_arg<_Tp, _Up> { }; //__replace_first_arg中type成员类型为_Tp<_Up>template<typename _Tp, typename _Up> //模板类特例化版本,_Tp有rebind成员函数时,调用此版本struct __rebind<_Tp, _Up,__void_t<typename _Tp::template rebind<_Up>::other>>{ using type = typename _Tp::template rebind<_Up>::other; }; //声明成员type类型为_Tp<_Up>的别名protected: //类型别名,_Tp为内存分配器template<typename _Tp>using __pointer = typename _Tp::pointer; //指针类型template<typename _Tp>using __c_pointer = typename _Tp::const_pointer;template<typename _Tp>using __v_pointer = typename _Tp::void_pointer;template<typename _Tp>using __cv_pointer = typename _Tp::const_void_pointer;template<typename _Tp> //以下在_Tp中如果有相应成员函数则定义相应成员为true_type或false_typeusing __pocca = typename _Tp::propagate_on_container_copy_assignment; //_Tp下成员template<typename _Tp>using __pocma = typename _Tp::propagate_on_container_move_assignment; //_Tp下成员template<typename _Tp>using __pocs = typename _Tp::propagate_on_container_swap; //_Tp下成员template<typename _Tp>using __equal = typename _Tp::is_always_equal; //_Tp下成员}; //__allocator_traits_basetemplate<typename _Alloc, typename _Up> //声明__alloc_rebind为模板类__rebind中成员type的别名using __alloc_rebind //模板类__allocator_traits_base下成员type在该声明点处可见= typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;//类allocator_traits,继承__allocator_traits_base,获取内存分配器的属性template<typename _Alloc>struct allocator_traits : __allocator_traits_base{typedef _Alloc allocator_type; //内存分配器typedef typename _Alloc::value_type value_type; //内存分配的类型//__detected_or_t<>等于__pointer<_Alloc>即_Alloc::pointer//内存分配器_Alloc下无__pointer定义时,使用value_type*作为指针类型pointerusing pointer = __detected_or_t<value_type*, __pointer, _Alloc>;private: //模板类,声明_Ptr成员type类型//当pointer为标准指针类型时,pointer_traits<pointer>::rebind<_Tp>等于_Tp*//当不为标准指针类型时,pointer_traits<pointer>::rebind<_Tp>等于__rebind<pointer,_Tp>::type//在__allocator_traits_base中__rebind<pointer,_Tp>的成员type为pointer<_Tp>//pointer<_Tp>即__detected_or_t<value_type*, __pointer, _Tp>template<template<typename> class _Func, typename _Tp, typename = void>struct _Ptr{ using type = typename pointer_traits<pointer>::template rebind<_Tp>; }; //type为指针类型template<template<typename> class _Func, typename _Tp> //模板类特例化版本struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>> //_Func为模板类,可接受内存分配器作为模板实参{ using type = _Func<_Alloc>; }; //_Func<_Alloc>获取type类型//模板类,声明_Diff下type为_A2::difference_type或pointer_traits<_Ptr>::difference_typetemplate<typename _A2, typename _PtrT, typename = void>struct _Diff{ using type = typename pointer_traits<_PtrT>::difference_type; };template<typename _A2, typename _PtrT>struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>>{ using type = typename _A2::difference_type; };//声明_Size下type为_A2::size_type or make_unsigned<_DiffT>::typetemplate<typename _A2, typename _DiffT, typename = void>struct _Size : make_unsigned<_DiffT> { };template<typename _A2, typename _DiffT>struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>>{ using type = typename _A2::size_type; };public: //类型别名using const_pointer = typename _Ptr<__c_pointer, const value_type>::type; //_Ptr下成员typeusing void_pointer = typename _Ptr<__v_pointer, void>::type;using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type;using difference_type = typename _Diff<_Alloc, pointer>::type; //_Diff下成员typeusing size_type = typename _Size<_Alloc, difference_type>::type; //_Size下成员type//__detected_or_t返回__pocca<_Alloc>的定义,若_Alloc下无__pocca定义则返回false_type//__pocca<_Alloc>为_Alloc::propagate_on_container_copy_assignmentusing propagate_on_container_copy_assignment= __detected_or_t<false_type, __pocca, _Alloc>;using propagate_on_container_move_assignment= __detected_or_t<false_type, __pocma, _Alloc>;using propagate_on_container_swap= __detected_or_t<false_type, __pocs, _Alloc>;using is_always_equal= __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>;template<typename _Tp> //重新封装__alloc_rebind,rebind_alloc<_Tp>为_Alloc<_Tp>using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;template<typename _Tp> //重新封装allocator_traits,萃取_Alloc<_Tp>的属性using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;//以下省略allocate、deallocate、construct、destroy、max_size}; //allocator_traits//_Alloc为allocator的特例化版本template<typename _Tp>struct allocator_traits<allocator<_Tp>>{using allocator_type = allocator<_Tp>;using value_type = _Tp;using pointer = _Tp*;using const_pointer = const _Tp*;using void_pointer = void*;using const_void_pointer = const void*;using difference_type = std::ptrdiff_t;using size_type = std::size_t;using propagate_on_container_copy_assignment = false_type;using propagate_on_container_move_assignment = true_type;using propagate_on_container_swap = false_type;using is_always_equal = true_type;template<typename _Up> //_Up的内存分配器allocator<_Up>using rebind_alloc = allocator<_Up>;template<typename _Up>//allocator<_Up>的属性萃取allocator_traits<_Up>using rebind_traits = allocator_traits<allocator<_Up>>;//以下封装allocator<_Tp>的成员函数static pointerallocate(allocator_type& __a, size_type __n){ return __a.allocate(__n); }static pointerallocate(allocator_type& __a, size_type __n, const_void_pointer __hint){ return __a.allocate(__n, __hint); }static voiddeallocate(allocator_type& __a, pointer __p, size_type __n){ __a.deallocate(__p, __n); }template<typename _Up, typename... _Args>static voidconstruct(allocator_type& __a, _Up* __p, _Args&&... __args){ __a.construct(__p, std::forward<_Args>(__args)...); }template<typename _Up>static voiddestroy(allocator_type& __a, _Up* __p){ __a.destroy(__p); }static size_typemax_size(const allocator_type& __a) noexcept{ return __a.max_size(); }static allocator_typeselect_on_container_copy_construction(const allocator_type& __rhs){ return __rhs; }}; //allocator_traits<allocator<_Tp>>} // namespace std

STL源码剖析(二)__alloc_traits特性相关推荐

  1. STL源码剖析学习二:空间配置器(allocator)

    STL源码剖析学习二:空间配置器(allocator) 标准接口: vlaue_type pointer const_pointer reference const_reference size_ty ...

  2. STL源码剖析---红黑树原理详解下

    转载请标明出处,原文地址:http://blog.csdn.net/hackbuteer1/article/details/7760584       算法导论书上给出的红黑树的性质如下,跟STL源码 ...

  3. STL源码剖析---deque

    一.deque的中控器       deque是连续空间(至少逻辑上看来如此),连续线性空间总令我们联想到array或vector.array无法成长,vector虽可成长,却只能向尾端成长,而且其所 ...

  4. STL源码剖析 map

    所有元素会根据元素的键值自动被排序 元素的类型是pair,同时拥有键值和实值:map不允许两个元素出现相同的键值 pair 代码 template <class T1,class T2> ...

  5. 《STL源码剖析》相关面试题总结

    一.STL简介 STL提供六大组件,彼此可以组合套用: 容器 容器就是各种数据结构,我就不多说,看看下面这张图回忆一下就好了,从实现角度看,STL容器是一种class template. 算法 各种常 ...

  6. STL源码剖析(十三)关联式容器之rb_tree

    STL源码剖析(十三)关联式容器之rb_tree 文章目录 STL源码剖析(十三)关联式容器之rb_tree 一.rb_tree的数据结构 二.rb_tree的迭代器 三.rb_tree的操作 3.1 ...

  7. C++ STL源码剖析 笔记

    写在前面 记录一下<C++ STL源码剖析>中的要点. 一.STL六大组件 容器(container): 各种数据结构,用于存放数据: class template 类泛型: 如vecto ...

  8. 【STL源码剖析】迭代器

    [STL源码剖析]迭代器 第3章 迭代器(iterators)与traits编程技法(<STL源码剖析> ) 3.1 迭代器设计思维--STL关键所在 3.2 迭代器(iterator)是 ...

  9. STL源码剖析---移动advance

    目录 一. 迭代器 二. 类型萃取机 2.1 处理类实现的迭代器 2.2 处理原生指针实现的迭代器 三. advance 3.1 iterator_category 3.2 激活重载机制 3.3 实现 ...

  10. STL(C++标准库,体系结构及其内核分析)(STL源码剖析)(更新完毕)

    文章目录 介绍 Level 0:使用C++标准库 0 STL六大部件 0.1 六大部件之间的关系 0.2 复杂度 0.3 容器是前闭后开(左闭右开)区间 1 容器的结构与分类 1.1 使用容器Arra ...

最新文章

  1. 千万级并发!如何设计一个多级缓存系统?
  2. 最新清华大学arXiv上传的深度学习摄像头运动估计论文
  3. java中servlet filter_lua学习笔记(二)仿java servlet中Filter功能
  4. cacti监控(3)配置cacti
  5. NB-IOT环境监测项目需求分析
  6. 制作五彩纸屑转场动效_何时以及如何将五彩纸屑添加到产品UI
  7. 用任意合法序列建立一棵二叉树(洛谷P1305题题解,Java语言描述)
  8. 【源码分析】微信小程序 - 01表单组件 - 01button - 实践
  9. 河北省科技创新平台用例图
  10. 360度测试:KAFKA会丢数据么?其高可用是否满足需求?
  11. java 为透明图片添加背景颜色
  12. python计算最大值最小值_python怎么求最大值最小值
  13. 科里奥利力的物理理解、推导与加速度变换
  14. 工作总结9:这一个月来犯的错
  15. 写给这批≥30岁的测试工程师 。
  16. echarts折线图设置圆点_echarts 设置折线图单个数据小圆圈样式
  17. idea启动报符号缺失,无法启动与构建
  18. sql 开发html,uap开发sql
  19. 影响TWS耳机发展的五大关键技术
  20. 用AI培养孩子学习兴趣:讯飞新一代智能学习机发布

热门文章

  1. js构造函数的实例成员和静态成员
  2. 短视频营销丨抖音KOL达人在传播中如何发挥作用?
  3. 查看linux说有文件系统,linux,查看文件系统
  4. 如何检测服务器的tcp端口是否通
  5. YDOOK:Python3.9: breakpoint(*args, **kws) 函数:在调用时进入调试器中 详细用法
  6. AnotherRedisDesktopManager集群连接报错cluster is ended
  7. 第3章 面向对象设计基础
  8. 360player免费全景图播放器更新-附开发教程-20200101
  9. 前端页面居中对齐总结
  10. 入门Rx-Observable的创建方式