内存处理工具–五个全局函数
前言
在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的复制品,放置于输出范围的相对位置上。
/*
*未初始化的拷贝,在已获得的内存上创建一些元素
*/
//POD标量的未初始化拷贝
template<class InputIterator,class ForwardIterator>
inline ForwardIterator _uninitialized_copy_aux(InputIterator first,InputIterator last,
ForwardIterater result,_type_true)
{
//从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中
memcpy(result,first,(last-first)*sizeof(*first));
return result+(last-first);
//return copy(first,last,result); 调用STL算法copy()
}
//non-POD的未初始化拷贝
template<class InputIterator,class ForwardIterator>
ForwardIterator _uninitial_copy_aux(InputIterator first,InputIterator last,
ForwardIterator result,_false_type)
{
//ForwardIterator cur=result;
int i=0;
for(;first!=last;++first,++i)
{
construct(result+i,*first);
}
return (result+i);
}
//判断该型别是否为POD型别
template<class InputIterator,class ForwardIterator,class T>
inline ForwardIterator _uninitiialized_copy(InputIterator first,InputIterator last,
ForwardIterator result,T*)
{
typedef typename _type_traits<T>::is_POD_type isPOD;
return _uninitialzed_copy_aux(first,last,result,isPOD());
//让编译器做参数推导
}
template<class InputIterator,class ForwardIterator>
inline ForwardIterator uninitialized_copy(InputIterator first,InputIterator last,
ForwardIterator result)
{
return _uninitialized_copy(first,last,result,value_type(result));
//利用value_type()萃取出first的value type
}
//针对char*和wchar_t*两种型别,采用最具效率的做法memmove(直接移动内存内容)来执行复制内容
inline char* uninitialized_copy(const char* first,const char* last,char* result)
{
memmove(result,first,last-first);
return result+(last-first);
}
inline wchar_t* uninitialized_copy(const wchar_t* first,const wchar_t* last,wchar_t result)
{
memmove(result,first,sizeof(wchar_t)*(last-first));
return result+(last-first);
}
如果你需要实现一个容器,uninitialized_copy()这样的函数会为你带来很大的帮助,因为容器的全区间构造函数通常以两个步骤完成:
(1)配置内存区块,足以包含范围内的所有元素。
(2)使用uninitialized_copy(),在该内存区块上构造元素。
C++标志规格书要求uninitialized_copy()具有“commit or rollback”语意,意思是要么“构造出所有必要的元素”,要么(当有任何一个copy constructor失败时)不构造任何东西。
uninitialized_fill()
uninitialized_fill()也能够使我们将内存配置与对象的构造行为分离开来。
如果[first,last)范围内的每个迭代器都指向未初始化的内存,那么uninitialized_fill()会在该范围内产生x(上式第三个参数)的复制品。换句话说,uninitialized_fill()会针对操作范围内的每个迭代器i,调用construct(&*i,x),在i所指之处产生x的复制品。
/*
* 未初始化的拷贝,以某一特定值初始化
*/
template<class ForwardIterator,class T>
inline void _uninitialized_fill_aux(ForwardIterator first,ForwardIterator last,
const T& value,_true_value)
{
fill(first,last,value);
}
template<class ForwardIterator,class T>
inline void _uninitialized_fill_aux(ForwardIterator first,ForwardIterator last,
const T& value,_false_value)
{
for(;first!=last;++first)
{
construct(first,value); //必须一个一个地构建
}
}
template<class ForwardIterator,class T>
inline void _uninitialized_fill(ForwardIterator first,ForwardIterator last,
const T& value)
{
typedef typename _type_traits<T>::is_POD_type isPOD;
_uninitialized_fill_aux(first,last,isPOD());
}
template<class ForwardIterator,class T>
inline void _uninitialized_fill_aux(ForwardIterator first,ForwardIterator last,
const T& value)
{
_uninitialized_fill(first,last value,value_type(first));
}
与uninitialized_copy()一样,uninitialized_fill()必须具备“commit or rollback”语意,换句话说,它要么产生出所有必要元素,要么不产生任何元素,如果有任何一个copy constructor丢出异常(exception),uninitialized_fill(),必须能够将已产生的所有元素析构掉。
uninitialized_fill_n()
uninitialized_fill_n()能使我们将内存配置与对象构造行为分离开来,它会为指定范围内的所有元素设定相同的初值。
如果[first,first+n)范围内的每一个迭代器都指向未初始化的内存,那么uninitialized_fill_n()会调用 copy constructor,在该范围内产生x(上式第三个参数——的复制品。也就是说,面对[first,first+n)范围内的每个迭代器i,uninitialized_fill_n()会调用construct(&*i,x),在对应位置产生x的复制品。
/*
*未初始化的拷贝,以某一特定数量n初始化
*/
template<class ForwardIterator,class Size class T>
inline ForwardIterator _uninitialized_fill_n_aux(ForwardIterator first,Size n,
const T& x,_true_type)
{
return fill_n(first,n,x);
}
template<class ForwardIterator,class Size class T>
inline ForwardIterator _uninitialized_fill_n_aux(ForwardIterator first,Size n,
const T& x,_false_type)
{
// ForwardIterator cur=result;
int i=0;
for(;i!=n;i++)
{
construct((T*)(first+i),x);
}
return (first+i);
}
template<class ForwardIterator,class Size,class T>
inline ForwardIterator uninitialized_fill_n(ForwardIterator first,Size n,
const T& x)
{
typedef typename _type_traits<T>::is_POD_type isPOD;
_uninitialized_fill_n_aux(first,n,x,isPOD());
}
template<class ForwardIterator,class Size,class T>
inline void _uninitialized_fill_aux(ForwardIterator first,ForwardIterator last,
const T& value)
{
uninitialized_fill_n(first,last value,value_type(first));
}
}
uninitialized_fill_n()也具有“commit or rollback”语意:要么产生所有必要的元素,否则就不产生任何元素。如果任何一个copy constructor丢出异常(exception),uninitialized_fill_n()必须析构已产生的所有元素。
总结
在这个五个全局函数中,我们可以看到,基本上是Traits和__type_traits技术的作用,方便内存处理,并且提高效率。
代码
construct.h
#ifdef _CONSTRUCT_H_
#define _CONSTRUCT_H_
#include<new> //使用placement new
#include"typetraits.h"
namespace EasySTL
{
template<class T1,class T2>
inline void construct(T1 *ptr1,const T2& value)
{
new(ptr1) T1(value); //placement new 调用T1::T1(value) 在已获取内存上创建内存
}
template<class T>
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*){}
}
#endif
uninitialized.h
#ifdef _UNINITIALIZED_H_
#define _UNINITIALIZED_H_
#include"construct.h"
#include"algorithm.h"
/*
* 将 内存配置 与 对象构造 分离开来
*/
namespace EasySTL
{
/*
*未初始化的拷贝,在已获得的内存上创建一些元素
*/
//POD标量的未初始化拷贝
template<class InputIterator,class ForwardIterator>
inline ForwardIterator _uninitialized_copy_aux(InputIterator first,InputIterator last,
ForwardIterater result,_type_true)
{
//从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中
memcpy(result,first,(last-first)*sizeof(*first));
return result+(last-first);
//return copy(first,last,result); 调用STL算法copy()
}
//non-POD的未初始化拷贝
template<class InputIterator,class ForwardIterator>
ForwardIterator _uninitial_copy_aux(InputIterator first,InputIterator last,
ForwardIterator result,_false_type)
{
//ForwardIterator cur=result;
int i=0;
for(;first!=last;++first,++i)
{
construct(result+i,*first);
}
return (result+i);
}
//判断该型别是否为POD型别
template<class InputIterator,class ForwardIterator,class T>
inline ForwardIterator _uninitiialized_copy(InputIterator first,InputIterator last,
ForwardIterator result,T*)
{
typedef typename _type_traits<T>::is_POD_type isPOD;
return _uninitialzed_copy_aux(first,last,result,isPOD());
//让编译器做参数推导
}
template<class InputIterator,class ForwardIterator>
inline ForwardIterator uninitialized_copy(InputIterator first,InputIterator last,
ForwardIterator result)
{
return _uninitialized_copy(first,last,result,value_type(result));
//利用value_type()萃取出first的value type
}
//针对char*和wchar_t*两种型别,采用最具效率的做法memmove(直接移动内存内容)来执行复制内容
inline char* uninitialized_copy(const char* first,const char* last,char* result)
{
memmove(result,first,last-first);
return result+(last-first);
}
inline wchar_t* uninitialized_copy(const wchar_t* first,const wchar_t* last,wchar_t result)
{
memmove(result,first,sizeof(wchar_t)*(last-first));
return result+(last-first);
}
/*
* 未初始化的拷贝,以某一特定值初始化
*/
template<class ForwardIterator,class T>
inline void _uninitialized_fill_aux(ForwardIterator first,ForwardIterator last,
const T& value,_true_value)
{
fill(first,last,value);
}
template<class ForwardIterator,class T>
inline void _uninitialized_fill_aux(ForwardIterator first,ForwardIterator last,
const T& value,_false_value)
{
for(;first!=last;++first)
{
construct(first,value); //必须一个一个地构建
}
}
template<class ForwardIterator,class T>
inline void _uninitialized_fill(ForwardIterator first,ForwardIterator last,
const T& value)
{
typedef typename _type_traits<T>::is_POD_type isPOD;
_uninitialized_fill_aux(first,last,isPOD());
}
template<class ForwardIterator,class T>
inline void _uninitialized_fill_aux(ForwardIterator first,ForwardIterator last,
const T& value)
{
_uninitialized_fill(first,last value,value_type(first));
}
/*
*未初始化的拷贝,以某一特定数量n初始化
*/
template<class ForwardIterator,class Size class T>
inline ForwardIterator _uninitialized_fill_n_aux(ForwardIterator first,Size n,
const T& x,_true_type)
{
return fill_n(first,n,x);
}
template<class ForwardIterator,class Size class T>
inline ForwardIterator _uninitialized_fill_n_aux(ForwardIterator first,Size n,
const T& x,_false_type)
{
// ForwardIterator cur=result;
int i=0;
for(;i!=n;i++)
{
construct((T*)(first+i),x);
}
return (first+i);
}
template<class ForwardIterator,class Size,class T>
inline ForwardIterator uninitialized_fill_n(ForwardIterator first,Size n,
const T& x)
{
typedef typename _type_traits<T>::is_POD_type isPOD;
_uninitialized_fill_n_aux(first,n,x,isPOD());
}
template<class ForwardIterator,class Size,class T>
inline void _uninitialized_fill_aux(ForwardIterator first,ForwardIterator last,
const T& value)
{
uninitialized_fill_n(first,last value,value_type(first));
}
}
#endif
End