【深度探索STL】空间配置器(四) 内存基本处理

前面分别学习了:

  1. 对象的构造和析构              :http://blog.csdn.net/wenqian1991/article/details/19545049
  2. 空间配置器之第一级配置器:http://blog.csdn.net/wenqian1991/article/details/19566499
  3. 空间配置器之第二级配置器:http://blog.csdn.net/wenqian1991/article/details/19605727

这里继续学习基于配置器之上的一些内存基本处理工具。主要剖析 SGI STL 源码(http ://www.sgi.com/tech/stl/download.html  v3.3)中的几个内存处理函数(由函数名可知,是对未初始化空间的初始化操作,即通过复制或赋值的方式初始化未初始化的空间):
uninitialized_copy(),uninitialized_copy_n(),uninitialized_fill(),uninitialized_fill_n()

先学习 uninitiated_copy()

//stl source code(v3.3)
//defined in <stl_uninitialized.h>
inline char* uninitialized_copy(const char* __first, const char* __last, char* __result) 
{
	memmove(__result, __first, __last - __first);
	return __result + (__last - __first);  //返回该连续区域的末尾
}

inline wchar_t*   // typedef unsigned short 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 _InputIter, class _ForwardIter>
inline _ForwardIter
uninitialized_copy(_InputIter __first, _InputIter __last, _ForwardIter __result)
{   
	//根据数值型别决议出最佳效率的函数
	return __uninitialized_copy(__first, __last, __result, __VALUE_TYPE(__result));
}

template <class _InputIter, class _ForwardIter, class _Tp>
inline _ForwardIter
__uninitialized_copy(_InputIter __first, _InputIter __last, _ForwardIter __result, _Tp*)
{
	typedef typename __type_traits<_Tp>::is_POD_type _Is_POD;   //判断数值型别
	//在C++中,我们把传统的C风格的struct叫做POD(Plain Old Data)对象

	return __uninitialized_copy_aux(__first, __last, __result, _Is_POD());
}

//如果copy construction 和 operator = 等效(POD type),并且 destructor is trivial 的情况 
template <class _InputIter, class _ForwardIter>
inline _ForwardIter
__uninitialized_copy_aux(_InputIter __first, _InputIter __last, _ForwardIter __result, __true_type)
{
	/*针对POD对象,其二进制内容是可以随便复制的*/
	return copy(__first, __last, __result);

	/*简化处理,详见<stl_algobase.h>
	inline _Tp* copy(const _Tp* __first, const _Tp* __last, _Tp* __result)
	{
	    memmove(__result, __first, sizeof(_Tp) * (__last - __first));
	    return __result + (__last - __first);
	}
	*/
}

/*如果copy construction 和 operator = 不等效,就需要调用 construct() 构造 */
template <class _InputIter, class _ForwardIter>
_ForwardIter
__uninitialized_copy_aux(_InputIter __first, _InputIter __last, _ForwardIter __result, __false_type)
{
	_ForwardIter __cur = __result;

	/*下面就是捕捉异常处理*/
	__STL_TRY{    //#define __STL_TRY  try
		for (; __first != __last; ++__first, ++__cur) //一个一个元素的构造,无法批量进行
		_Construct(&*__cur, *__first);   //每个对象都以其它对象为蓝本进行构造,使用的是 placement new
		return __cur;
	}
	/*commit or rollback:要么构造出所有必要元素,
	要么(当有任何一个 copy construct 失败时)不构造任何东西,保证所有对象都被析构*/
	__STL_UNWIND(_Destroy(__result, __cur));
	//#define __STL_UNMIND(action)  catch(...) { action; throw;}
}
POD就是标量型别或传统的C struct 型别,POD 型别必然拥有 trivial ctor / dtor / copy / assignment 函数,因此我们可以对POD型别进行判断,从而决议出最有效率的初值填写手法

不难发现上面 uninitiated_copy() 后,返回的是指向 copy 后的区块末端。

uninitiated_copy_n() 则是向指定欲初始化空间初始化(复制)指定大小已初始化空间的指定值(有点拗口)。

template <class _InputIter, class _Size, class _ForwardIter>
inline pair<_InputIter, _ForwardIter>
uninitialized_copy_n(_InputIter __first, _Size __count, _ForwardIter __result)
{
	//最后一个形参判断迭代器 first 的类别
	return __uninitialized_copy_n(__first, __count, __result, __ITERATOR_CATEGORY(__first));
}

//函数返回两个值,采用 pair 对组
//迭代器型别为支持随机存取的迭代器,涵盖所有指针运算能力,可以直接使用uninitialized_copy()进行复制
template <class _RandomAccessIter, class _Size, class _ForwardIter>
inline pair<_RandomAccessIter, _ForwardIter>
__uninitialized_copy_n(_RandomAccessIter __first, _Size __count, _ForwardIter __result, random_access_iterator_tag)
{
	_RandomAccessIter __last = __first + __count;
	return pair<_RandomAccessIter, _ForwardIter>(__last, uninitialized_copy(__first, __last, __result));
}

//迭代器为只读型别,所指的对象不允许外界改变
template <class _InputIter, class _Size, class _ForwardIter>
pair<_InputIter, _ForwardIter>
__uninitialized_copy_n(_InputIter __first, _Size __count, _ForwardIter __result, input_iterator_tag)
{
	/*针对输入范围内的每一个迭代器,函数会调用construct()函数产生迭代器所指对象的复制品,
	放置于输出范围的相应位置上*/
	_ForwardIter __cur = __result;
	__STL_TRY{        
		for (; __count > 0; --__count, ++__first, ++__cur)
		_Construct(&*__cur, *__first);
		return pair<_InputIter, _ForwardIter>(__first, __cur);
	}
	__STL_UNWIND(_Destroy(__result, __cur));
}
上面函数都是返回 pair 对组类型。其实就是返回两个值,一个是 “只读” 型别的迭代器(_InputIter),一个是允许 “写入型” 的迭代器(_ForwardIter)。
下面这个函数 uninitiated_fill() 和 uninitiated_copy() 操作很像,只不过前者是赋值,后者是复制。

//迭代器类型为“写入型”。该函数的功能就是给迭代器指定范围内赋值
//具体实现过程参考函数 uninitialized_copy()
template <class _ForwardIter, class _Tp>
inline void uninitialized_fill(_ForwardIter __first, _ForwardIter __last, const _Tp& __x)
{
	__uninitialized_fill(__first, __last, __x, __VALUE_TYPE(__first));
}

//判断数值型别,同 uninitialized_copy()
template <class _ForwardIter, class _Tp, class _Tp1>
inline void __uninitialized_fill(_ForwardIter __first, _ForwardIter __last, const _Tp& __x, _Tp1*)
{
	typedef typename __type_traits<_Tp1>::is_POD_type _Is_POD;
	__uninitialized_fill_aux(__first, __last, __x, _Is_POD());
}

template <class _ForwardIter, class _Tp>
inline void
__uninitialized_fill_aux(_ForwardIter __first, _ForwardIter __last, const _Tp& __x, __true_type)
{
	fill(__first, __last, __x);
	/*简化处理,参见<stl_algobase.h>
	template <class _ForwardIter, class _Tp>
	void fill(_ForwardIter __first, _ForwardIter __last, const _Tp& __value) 
	{
		for ( ; __first != __last; ++__first)
			*__first = __value;
	}
	*/
}

template <class _ForwardIter, class _Tp>
void
__uninitialized_fill_aux(_ForwardIter __first, _ForwardIter __last, const _Tp& __x, __false_type)
{
	_ForwardIter __cur = __first;
	__STL_TRY{
		for (; __cur != __last; ++__cur)
		_Construct(&*__cur, __x);
	}
	__STL_UNWIND(_Destroy(__first, __cur));
}
下面的函数 uninitiated_fill_n() 则是向指定欲初始化空间初始化(赋值)指定大小空间的指定值。

template <class _ForwardIter, class _Size, class _Tp>
inline _ForwardIter
uninitialized_fill_n(_ForwardIter __first, _Size __n, const _Tp& __x)
{
	return __uninitialized_fill_n(__first, __n, __x, __VALUE_TYPE(__first));
}

template <class _ForwardIter, class _Size, class _Tp, class _Tp1>
inline _ForwardIter
__uninitialized_fill_n(_ForwardIter __first, _Size __n, const _Tp& __x, _Tp1*)
{
	typedef typename __type_traits<_Tp1>::is_POD_type _Is_POD;
	return __uninitialized_fill_n_aux(__first, __n, __x, _Is_POD());
}

template <class _ForwardIter, class _Size, class _Tp>
_ForwardIter
__uninitialized_fill_n_aux(_ForwardIter __first, _Size __n, const _Tp& __x, __false_type)
{
	_ForwardIter __cur = __first;
	__STL_TRY{
		for (; __n > 0; --__n, ++__cur)
		_Construct(&*__cur, __x);
		return __cur;
	}
	__STL_UNWIND(_Destroy(__first, __cur));
}

template <class _ForwardIter, class _Size, class _Tp>
inline _ForwardIter
__uninitialized_fill_n_aux(_ForwardIter __first, _Size __n, const _Tp& __x, __true_type)
{
	return fill_n(__first, __n, __x);
	/*简化处理,参见<stl_algobase.h>
	template <class _OutputIter, class _Size, class _Tp>
    _OutputIter fill_n(_OutputIter __first, _Size __n, const _Tp& __value)
	{
		for ( ; __n > 0; --__n, ++__first)
			*__first = __value;
		return __first;
	}
	*/
}
STL 定义的这几个全局函数(包括前面介绍的用于构造的 construct() 和 用于析构的 destroy()),作用于未初始化空间上,这样的功能对于容器的实现很有帮助。

参考资料:《STL 源码剖析》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值