STL空间配置器(一)

来源:互联网 发布:淘宝封店支付宝还能用 编辑:程序博客网 时间:2024/05/16 12:25

这里主要说的是具备次配置力的SGI空间配置器。

SGI STL的配置器与众不同,也与标准规范不同,其名称是alloc而不是allocator,而且不接受任何参数。

比如:

Vector<int,std::allocator<int>>  iv; //此写法错误

Vector<int,std::alloc>  iv;//此写法正确

注意:

SGI STL的每一个容器都已经指定其缺省的空间配置器为alloc

SGI STL也定义了一个符合部分标准,名为allocator的配置器,但是SGI从未使用过它,也不建议我们使用,主要是因为效率不佳,他只把C++::operator new::operator delete做一层薄薄的包装而已。

 

下面我们要说的是SGI的特殊的空间配置器。

 

SGI特殊的空间配置器----->std::alloc

我们所习惯的C++内存配置和内存释放的操作是:

先配置内存,再构造对象。

先对象析构,再释放内存。

 

在这里,为了精密分工,所以决定将这个两个阶段操作区分开来处理。

内存配置操作由alloc::allocator()负责,内存释放操作由alloc::deallocator()负责。

对象构造操作由::construct()负责,对象析构操作由::destroy()负责。

(就是将内存配置,释放和对象构造,析构分开来进行)

 

配置器定义于<memory>之中,而SGI<memory>内包含以下两个文件:

#include  <stl_alloc.h>          //负责内存空间的配置与释放

#include  <stl_construct.h>      //负责对象内容的构造与析构


如下图:


1.下面一起来看一下构造和析构基本工具:construct() destroy()

以下是<stl_construct.h>的部分内容:

#include <new.h>template <class T1,class T2>inline void construct(T1 * P,const T2& value){new(p) T1(value); //placement new 的调用}/*Placement new它用于在给定的内存中初始化对象(注意:此处是已经给定的内存)Placement new的调用方式是:new(p)  T1(value);  //(其中p是已经申请好的内存)*///以下是destroy()第一版本,接受一个指针template <class T>inline void destroy(T* pointer){poniter-> ~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 destructortemplate <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*){}

由以上代码我们可以知道:

(1)construct()函数接受一个指针p和一个初值value,该函数的用途就是将初值设定到指针所指的空间上。(所以此处用的是C++中的placement new)

(2)Destroy()函数有两个版本

     a)第一个版本接受一个指针,准备将该指针所指的对象析构掉(此处直接调用析构函数即可)

     b)第二个版本是接受两个迭代器firstlast,准备将[firstlast)范围内的所有对象析构掉,我们不知道这个范围有多大,万一很大,而每个对象的析构函数都无关痛痒,那么一次次调用个这些无关痛痒的析构函数对效率是一种伤害。因此,这里首先利用value_type()获得迭代器所指对象的型别,再利用_type_traits<T>判断该型别的析构函数是否无关痛痒,若是(_true_type),则什么也不做就结束;若否(_false_type),这才以循环方式巡防整个范围,并在循环中每经历一个对象就调用第一版本的destroy().


注意:这两个作为构造和析构之用的函数被设计为全局函数,符合STL的规范。

STL还规定配置器必须拥有名为construct()destroy()的两个成员函数。

(然而真正在SGI STL中大显身手的std::alloc的配置器并未遵守这一规则)

原创粉丝点击