STL:construct 与 destroy

Posted 小键233

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STL:construct 与 destroy相关的知识,希望对你有一定的参考价值。

STL 中关于对象的构造和销毁是使用construct 和 destroy 函数 的。
这个内容写在文件stl_construct.h 中。

_type_traits

在讲主题之前,有必要介绍一个_type_traits 与若干概念。
简单而言,这个类的作用就是萃取出我们需要的各种内容。

它的模板代码如下:

//POD  的意思是:Plain Old Data ,即标量型或传统的C struct 型别
template<typename T>
struct _type_traits

    typedef _false_type has_trivial_default_constructor;
    typedef _false_type has_trivial_copy_constructor;
    typedef _false_type has_trivial_assignment_operator;
    typedef _false_type has_trivial_destructor;
    typedef _false_type is_POD_type;
;

它想要表达的意思是,你给我的模板参数,它是否有平凡的构造函数(trivial_constructor)、平凡的复制构造函数、平凡的赋值函数、平凡的析构函数与及是否是POD 变量。

POD 变量的解析:

Plain Old Data ,即标量型或传统的C struct 型别

POD 变量显然满足上面列的条件。
那需要区分是和否,我们就需要两个类:

struct _true_type ;
struct _false_type ;

这两个类的作用就是用于区分,从而进行函数重载。对的,traits 技术就是基于函数重载完成的。

下面会有一堆的特化版本,这里只列出一种:

template<> struct _type_traits<bool>

    typedef _true_type has_trivial_default_constructor;
    typedef _true_type has_trivial_copy_constructor;
    typedef _true_type has_trivial_assignment_operator;
    typedef _true_type has_trivial_destructor;
    typedef _true_type is_POD_type;
;

除了bool ,还有其他的内置变量。
对于我们自定义的类,都是默认为false_type 的。如果你希望修改,那就要自己去特化它。

construct

construct 的函数比较简单,只要用placement new 就可以了:

template<typename T1, typename T2>
inline void construct(T1* p, const T2& value)

    new (p) T1(value);



template<typename T1>
inline void construct(T1* p)

    new (p) T1;

destroy

destroy 函数的行为就有一点点复杂了,它会依据萃取出的类型信息,选择不同的执行函数。如果是trivial_destructor, 那么什么都不做。否则一一析构。
第一个版本,只需要析构一个变量:

template<typename T1>
inline void destroy(T1* p)

    p->~T1();

那就乖乖析构好了。注意,析构函数是可以在类外显示调用的,构造函数就不可以。我第一次看到的时候,非常震惊。

第二个版本是接受一个区间范围,然后执行合适的行为。

template<typename Forward_iterator, typename T>
inline void _destroy_aux(Forward_iterator first, Forward_iterator last, T*)

    typedef typename _type_traits<T>::has_trivial_destructor trivial_destructor;
    _destroy_aux(first, last, trivial_destructor() );


//第二个版本,如果析构函数是trivial destructor 那就什么都不做
template<typename Forward_iterator>
inline void _destroy_aux(Forward_iterator first, Forward_iterator last, _true_type)  

//第三个版本,要一一调用
template<typename Forward_iterator>
inline void _destroy_aux(Forward_iterator first, Forward_iterator last, _false_type)

    for(; first!=last; ++first)
    
        destroy(&*first);
    


template<typename Forward_iterator>
inline void destroy(Forward_iterator first, Forward_iterator last)

    //利用trait 技术,进而求取最合适的析构函数
    //value_type 就是把first 中的实际类型给提取出来
    _destroy_aux(first, last, _value_type(first) );

温馨提示,从下往上看。
_value_type 函数的定义如下:

//为什么不直接返回pointer呢?
//我想是因为不想被const 干扰吧
template<typename Iter>
inline typename iterator_traits<Iter>::value_type* _value_type(const Iter& )

    return static_cast< typename iterator_traits<Iter>::value_type* > (0);

返回这个类型的指针,这是为了获得这个类型的信息。
那这里又遇到了iterator_traits,看这个:traits
(果真好烦)

最后进行一些特化:


inline void destroy(char*, char* ) 
inline void destroy(int*, int* ) 
inline void destroy(long*, long* ) 
inline void destroy(float*, float* ) 
inline void destroy(double*, double* ) 
inline void destroy(wchar_t*, wchar_t* ) 

nice ,基本算是完成了。

以上是关于STL:construct 与 destroy的主要内容,如果未能解决你的问题,请参考以下文章

SGI-STL简记-构造类型萃取特性未初始化解析

STL之空间配置器allocator

STL源代码分析(ch2 内存分配)概述

STL源码剖析 第二章 空间配置器

stl_内存基本处理工具

STL源码剖析之allocator