仿写stl空间配置器
来源:互联网 发布:网络安全员资格证书 编辑:程序博客网 时间:2024/05/16 04:36
下图就是STL的层次分布图,当然还缺少一些组件,比如数值处理,pair对组,string,智能指针以及valarray数组等等,其中实现的难点主要集中在几个地方,分别是map红黑树的实现,heap算法体系,函数配接器,流迭代器。尤其是函数配接器,他的内部实现简直是穷尽一切顶尖技巧,令人叹为观止,先从最左边的内存分配器开始,因为他是所有的核心!
对于内存分配器其实并不陌生,比如每个操作系统有自己的内存分配器,ACE里面有个ACE_allocatir分配器,所以STL也一样,他的的内存分配器(空间配置器)在标准库中充当了异常重要的角色,所有的内存分配,管理,释放都是由他控制,SGI的设计理念就是把内存管理这一块红灯区抽离出来,作为模版参数传递进去每个容器
由于STL实现版本众多,这里我先给出了一个分配器的可用接口,参照的是微软的STL实现版本而非SGI版本,但是他无疑是很好的一个入门点!
比如在vector:
template<class T,class Alloc<T> = allocator<T> >
class vector.........
他使用的是内置的默认内存分配器,在上图中我们看到有两个分配器,这是SGI STL中的高级之处,实作了多级内存分配,利用内存池实现效率上的优化,同时也减少了内存碎片的可能性。
在这之前需要知道两个全局函数 ::operator new 和 ::operator delete ,注意不要把他们和一般的new delete混为一谈,我们的运算符new在分配内存的时候同时调用对象的构造函数初始化内存,而::operator new只是分配内存,并不调用构造函数,这是实现一块无初始化内存池的关键点,同理delete。
另外还需要了解placement new运算符,他是定位运算符,并不分配内存,只是定位到某一已分配区域!
这里我们先实现一个能跟标准容器接口的分配器类,他并不高明,但是体现了标准分配器的必要特性,其实从某个角度说属于SGI版本的一级分配器的外观,SGI在分配内部使用的时malloc并做了一些必要措施和优化而已:
- template<class _Ty>
- struct Allocator_base
- { //配置器基类
- typedef _Ty value_type;
- };
- template<class _Ty>
- struct Allocator_base<const _Ty>
- { //配置器特化于const的基类
- typedef _Ty value_type;
- };
- template<class _Ty>
- class Allocator
- :public Allocator_base<_Ty>
- {
- public:
- //配置器内部型别
- typedef typename std::size_t size_type;
- typedef typename std::ptrdiff_t difference_type;
- typedef _Ty* pointer;
- typedef const _Ty* const_pointer;
- typedef _Ty& reference;
- typedef const _Ty& const_reference;
- typedef Allocator_base<_Ty> _Mybase;
- typedef typename _Mybase::value_type value_type;
- //配置器型别转换
- template<class _other>
- struct rebind
- {
- typedef Allocator<_other> other;
- };
- //地址函数定义
- pointer address(reference value)const{
- return &value;
- }
- const_pointer address(const_reference value)const{
- return (const_pointer)&value:
- }
- //默认构造函数 什么都不干
- Allocator() throw() {}
- //默认复制构造
- Allocator(const Allocator &)throw() {}
- //不同配置器的复制构造
- template<class _otherAll>
- Allocator(const Allocator<_otherAll> &)throw() {}
- //析构函数
- ~Allocator()throw() {}
- //返回能分配的最大内存
- size_type max_size()const throw()
- { //借助数值函数
- numeric_limit<size_type>::max() /sizeof(_Ty);
- }
- //分配未构造的内存待用
- pointer allocate(size_type num,
- typename Allocator<void>::const_pointer hint= 0)
- {
- return (pointer)(::operator new(num * sizeof(_Ty)) );
- }
- //在内存中构造对象
- void construct(pointer p,const_reference value)
- {
- new(p) _Ty(value);
- }
- //析构内存中的对象
- void destroy(pointer p)
- {
- p->~_Ty();
- }
- void deallocate( pointer p, size_type size )
- {
- ::operator delete(p);
- }
- //为了跟标准配置器接轨,这里只能返回true,下一个只能返回false
- bool operator==(Allocator const& a) const
- { return true; }
- bool operator!=(Allocator const& a) const
- { return !operator==(a); }
- };
- //allocator模版特化于类型void的类
- template<> class Allocator<void>
- {
- public:
- typedef void _Ty;
- typedef _Ty* pointer;
- typedef const _Ty* const_pointer;
- typedef _Ty value_type;
- template<class _other>
- struct rebind
- {
- typedef Allocator<_other> other;
- };
- Allocator()throw()
- { //还是一样,什么都不干
- }
- Allocator(const Allocator<_Ty>& )throw()
- { //复制构造,什么都不干
- }
- template<class _Other>
- Allocator(const Allocator<_Other>&) throw()
- {
- }
- template<class _Other>
- Allocator<_Ty>& operator=(const Allocator<_Other>&)
- {
- return (*this);
- }
- };
最开始是两个基类,这两个基类没有任何成员,只有一个内置型别,这两个基类不是必须的,可以略过,只是体现一种好的设计而已,最后一个类是模版特化了一个void类型,这样做也只是为了使用void的时候不发生未定义行为,从这一点可以看到STL对各种可能的情况都做了充分的预料,我们主要来看Allocator类!
刚开始定义了一对typedef,这是为分配器类定义一堆内置型别,其实也可以不定义啊,只不过在STL中都这样定义,构建出一种统一的类型型别,方便管理和可读性
接下来的
template<class _other>
struct rebind
{
typedef Allocator<_other> other;
};
这是一个分配器转换方式,可以方便的转换为为另一种类型服务的分配器,比如说我们构造的是T类,如果需要构造T*的时候,可以这样使用
Allocator<T>::rebind<T*>::other pAllocator;
这样pAllocator就是一个为T*服务的分配器,具体参考《STL标准程序库》!
该类接下来的函数都是标准接口必须的,不能少任何一个,其中有变动的是这四个 allocate deallocate destory construct
allocate函数分配一片连续的未被构造的空间备用,
deallocate 函数释放空间
construct函数调用布局new,同时调用构造函数,对象被new定位在指定位置(自定义的话可以获取自定义数据来源)
destory 函数调用析构函数,
这个分配器还是很简单的,就只需要注意那几点,所以我们在写自己的分配器并希望和标准容器接口时,要提供应有的接口
使用这个分配器,直接拿来当作SGI STL版本的入口点,测试程序:
- #include <iostream>
- #include <list>
- #include <vector>
- #include <algorithm>
- #include "allocator.h"
- using namespace std;
- int _tmain(int argc, _TCHAR* argv[])
- {
- std::vector<double,Allocator<double> > vec_double;
- std::list<int,Allocator<int> > list_int;
- for(int i=0;i<60;i++)
- {
- list_int.push_back(i);
- vec_double.push_back( double(i)/3 );
- }
- list<int,Allocator<int> >::iterator it = list_int.begin();
- vector<double,Allocator<double> >::iterator io = vec_double.begin();
- cout<<"list test:"<<endl;
- for(; it!= list_int.end();++it)
- cout<<*it<<" ";
- cout<<endl<<endl;
- cout<<"vector test:"<<endl;
- for(;io!= vec_double.end();++io)
- cout<<*io<<" ";
- system("pause");
- return 0;
- }
- 仿写stl空间配置器
- 一步一步写STL:空间配置器(1)
- 一步一步写STL:空间配置器 (1)
- 一步一步写STL:多级空间配置器(上)
- 【STL】STL空间配置器
- STL空间配置器
- STL空间配置器
- STL空间配置器
- 【STL】空间配置器
- STL空间配置器
- STL----空间配置器
- STL-空间配置器
- STL空间配置器
- STL空间配置器
- STL空间配置器
- STL空间配置器
- STL-空间配置器
- STL空间配置器
- 创业后期的新鲜好投资 必选微信营销
- QT创建和使用动态链接库
- drag a column here to group by this column
- 简明python教程学习笔记之九-序列的通用操作(索引和切片)
- onreadyStateChange
- 仿写stl空间配置器
- APK签名和优化对齐验证
- CACHE 函数 for ti
- 上海率先开放政府数据 医院床位车位信息均可查
- list集合去除重复对象
- 汉罗塔问题
- 解决cocostudio各种痛恨的控件Reader 的内存泄露
- windows 网络编程总结
- 天气预报接口(weather.com.cn)