STL 空间配置器(一)
一. 概述
空间配置器包含对象的构造与析构,内存的管理,以及其它一些全局函数。当调用new创建一个对象时,需要进行两个阶段的操作:内存分配与对象构造。同样的,当调用delete释放对象时也要进行对象的析构与内存回收。相较于对象的构造与析构,内存的管理会麻烦一些,因此先从简单的开始讨论。
二.构造与析构
在stl中对象的构造操作由::construct()负责,对象析构操作由::destory()负责。这两个函数都定义在<stl_construct.h>头文件中。
2.1对象的构造
::construct()函数有两个重载:
// 接收一个指向内存空间的执政__p 和 初值__value作为参数
template<class _T1, class _T2>
inline void construct(_T1* __p, const _T2& __value)
{
new (__p) _T1(__value);
}
// 只接收一个指向内存空间的执政__p
template<class _T1>
inline void construct(_T1* __p)
{
new (__P) _T1();
}
其中的new操作与平时使用的方式不同,“new(指针) 类型(值)” 这种用法是在一个已经分配了空间的地址上重新构造对象。例如: int a = 3; int *p = &a; new((void*)p) int(5); cout << *p;此时的输出结果就是5。
2.2 对象的析构
::destory()函数也有两种重载,一种接收一个指针,析构该指针所指之物。第二个版本接收两个迭代器,将[first, last)范围内的所有对象析构掉。
对于第一种,没有好解释的,直接调用析构函数,代码如下:
template <class _Tp>
inline void distory(_Tp* __pointer) {
__pointer->~Tp();
}
对于第二种,由于不知道迭代器的范围,万一很大,而对象为基本类型,那么会损失效率。为了避免这种情况,slt中采用了两种技术来避免:对模板函数的特化与萃取机的使用。
template <class _ForwardIterator>
inline void destroy(_ForwardIterator __first, _ForwardIterator __last) {
__destroy(__first, __last, __VALUE_TYPE(__first));
}
先说模板函数的特化:
stl中为用基础类型指针做为迭代器的调用,利用模板函数的特化进行了第一次区分:
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*) {}
这样以基础类型指针为参数的调用便不会调用析构函数。
接下来,stl为了区别出普通迭代器所指数据是否需要进行析构操作,而使用了两次萃取操作,第一次使用__VALUE_TYPE萃取出迭代器所指数据的类型,以该类型的对象为参数调用__destory()函数
template <class _ForwardIterator, class _Tp>
inline void
__destroy(_ForwardIterator __first, _ForwardIterator __last, _Tp*)
{
typedef typename __type_traits<_Tp>::has_trivial_destructor
_Trivial_destructor; // 萃取机制
__destroy_aux(__first, __last, _Trivial_destructor());
}
若类型Tp有析构函数则_Trivial_destructor的类型为struct __false_type,否则为 struct __true_type,以该类型的对象为参数调用重载函数__destory_aux()
template <class _ForwardIterator>
void
__destroy_aux(_ForwardIterator __first, _ForwardIterator __last, __false_type)
{
for ( ; __first != __last; ++__first)
destroy(&*__first);
}
template <class _ForwardIterator>
inline void __destroy_aux(_ForwardIterator, _ForwardIterator, __true_type) {}
关于stl萃取机的实现在其它博文中说明。
三.内存的分配与释放
见博文《STL 空间分配器(二)》
上一篇: 被辞退,被留下,从来都不是看能力!
下一篇: iOS Dark Mode快速适配