内存处理工具–五个全局函数
前言
在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的复制品,放置于输出范围的相对位置上。
/*
*未初始化的