STL源码学习系列五: 内存处理工具(construct,destroy,uninitialized_copy,uninitialized_fill,uninitialized_fill)

内存处理工具–五个全局函数


前言

在STL中,内存处理时很关键的,特别是对于容器的实现,内存处理相当的重要。为了实现内存配置跟对象的构造行为分离开来,STL定义的五个基本全局函数,这五个全局函数中,贯穿在里面的基本上是Traits和__type_traits技术,方便内存处理,并且提高效率。有关Traits技术见前文编程技法(Traits).

STL五个全局函数(方便内存处理,并且提高效率)分别是:
construct(),destroy(),uninitialized_copy(),uninitialized_fill(),uninitialized_fill_n();

以下分别对这些函数进行讲解。


构造基本工具:construct()

这里写图片描述
上述construct()接受一个指针p和一个初值value,该函数的用途就是将初值设定到指针所指的空间上。C++的placement new 运算子可用来完成这一任务。

 template<class T1,class T2>
 inline void construct(T1 *ptr1,const T2& value)
 {
     new(ptr1) T1(value);  //placement new 调用T1::T1(value) 在已获取内存上创建内存
 }

析构基本工具:destroy()

这里写图片描述
destroy()有两个版本,第一版本接受一个指针,准备将该指针所指之物析构掉。这很简单,直接调用该对象的析构函数即可。第二版本接受first和last两个迭代器,准备将[ first, last )范围内的所有对象析构掉(注意,这是一个左闭右开的范围)。如果范围很大,而每个对象的析构函数都无关痛痒(所谓trivial destructor),那么一次次调用这些无关痛痒的析构函数,对效率是一种伤害。因此,这里首先利用value_type()获得迭代器所指对象的型别,再利用_type_traits判断该型别的析构函数是否无关痛痒。若是(_true_type),则什么也不做就结束;若否(_false_type),这才以循环方式巡防整个范围,并在循环中每经历一个对象就调用第一个版本的destroy()。

    inline void destroy(T *ptr)
    {
        ptr->~T();   //调用 dtor ~T()
    }

    //判断元素的数值型别(valut type)是否有 trivial destructor...
    template<class ForwardIterator,class T>
    inline void destroy(ForwardIterator first, ForwardIterator last, T*)
    {
        typedef typename _type_traits<T>::has_trivial_destructor trivial_destructor;
        _destroy(first,last,trivial_destructor());
    }

    //如果元素的数值型别(valut type)有 trivial destructor...
    template<class ForwardIterator>
    inline void _destory(ForwardIterator first, ForwardIterator last, _true_type){}

    //如果元素的数值型别(valut type)有 non-trivial destructor...
    template<class ForwardIterator>
    inline void _destroy(ForwardIterator first, ForwardIterator last, _false_type)
    {
        for(;first!=last;++first)
            destroy(&*first);
    }

    template<class ForwardIterator>
    inline void destroy(ForwardIterator first, ForwardIterator last)
    {
        typedef typename _type_traits<ForwardIterator>::is_POD_type is_POD;
        _destroy(first,last,is_POD());
     }

    //针对char* wchar_t*的特化版
    inline void destroy(char*, char*){}
    inline void destroy(wchar_t*, wchar_t*){}
}

未初始化空间的复制与初始化

三个函数是uninitialized_copy(),uninitialized_fill(),uninitialized_fill_n,分别对应于高层次函数copy()、fill()、fill_n()。

以下分别介绍这三个函数的实现法,其中所呈现的iterators(迭代器)、value_type()、_type_traits、_true_type、_false_type、is_POD_type等实现技术,见前文迭代器(Iterator).

三个内存基本函数的泛型版本与特化版本:
这里写图片描述


uninitialized_copy()

uninitialized_copy()使我们能够将内存的配置和对象的构造行为分离开来。

如果作为输出目的地的[result,result+(last-first))范围内的每一个迭代器都指向为初始化区域,则uninitialized_copy()会使用copy constructor,给身为输入来源之[first,last)范围内的每一个对象产生一份复制品,放进输出范围中。换句话说,针对输入范围内的每一个迭代器i,该函数会调用construct(&*(result+(i-first)),*i),产生*i的复制品,放置于输出范围的相对位置上。

 /*
     *未初始化的
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值