STL源码剖析:【2】空间配置器-stl_construct.h

SGI特殊空间配置器:std::alloc

new 运算符含有两个阶段的过程:(1):申请内存(内存分配) (2)调用构造函数初始化 同理delete也有两个过程。

为了精密分工STL allocator决定将两个阶段操作区分开来: 内存配置与释放alloc::allocate()与alloc::deallocate()完成

对象构造过程由::construct 和::deconstruct(destroy)完成  分别对应<memory>下的<stl_alloc.h>和<stl_construct.h>

memory :  分为

1.<stl_construct.h> 包含全局函数:construct/destroy

2.<stl_alloc.h> 包含一二级配置器 ,命名为 alloc

3.<stl_uninitialized.h> 包含几个全局函数用来填充Fill和复制Copy大块内存数据 :

  • un_initialized_copy  
  • un_initialized_fill 
  • un_initialized_fill_n 

Construct:

首先讲一下stl_construct.h中的construct与destroy函数。

template<class T1,class T2>

    inline void construct(T1 *p,const T2 &value){

            new (p) T1(value);   // placement new 定向 new , p为Raw(原生)内存地址,value为存储内容

            //new 操作上面讲过,已经分为了明显的两个过程,内存分配以及初始化,现在则是对内存分配之后的内存

           //的初始化操作 , 即对特定内存地址进行对象初始化 }

 

template<class T1,class T2> // destroy第一个版本

inline void destroy (T1 *p) { p->~p();}  //调用对象析构函数

 

template<class ForwardIterator> // destroy第二个版本(为迭代器iterator提供接口)

inline void destroy (ForwardIterator first,ForwardIterator last) {

          _destroy(first,last,value_type(value));}  //调用对象析构函数

 

template<class ForwardIterator> // 第二个版本内部调用

inline void _destroy(ForwardIterator first,ForwardIterator last) {

         typedef typename _type_traits<T>::has_trivial_destruct trivial_destruct

          _destroy_aux(first,last,value_type(value),trivial_destruct());

}  //调用对象析构函数

 

template<class ForwardIterator> // has trivial destruct is false

inline void _destroy_aux(ForwardIterator first,ForwardIterator last, _false_type) {

       for( ; first<last ; first++)

             destroy(&*first);}  //调用对象析构函数

template<class ForwardIterator> // has trivial destruct is true

inline void _destroy_aux(ForwardIterator first,ForwardIterator last, _true_type) {}  //空函数


   STL源码剖析:【2】空间配置器-stl_construct.h


图片来源:STL源码剖析p52

文中特别指出,has_trivial_destructor 的介入使得调用迭代器对一块内存进行destruct的时候,会提高效率(因为调用没有必要的destruct是对性能的降低),其中trivial指代无意义的,无用的 ,与之相反的是no-trivial 有用的。

在深入理解C++对象模型一书中说明:C++中,编译器并不会对所有的Class都会提供一个默认的construct/deconstruct函数,只在以下5中有必要情况中出现:

  1. 内聚对象即class object memeber 中提供显示的默认构造函数
  2. 基类中提供显示的默认构造函数
  3. 含有virtual修饰的函数
  4. 基类中含有virtual修饰的函数
  5. 虚继承某一Class

使用has_trivial_destructor ,对不具有或者trivial的destruct的屏蔽,在first与last之间有很多的对象的时候是性能提升的