STL内存空间的配置/释放与对象内容的构造/析构,是分开进行的。
对象的构造、析构
对象的构造由construct函数完成,该函数内部调用定位new运算符,在指定的内存位置构造对象。如下:
template <typename T1, typename T2> inline void construct(T1 *p, const T2& value) { //定位new new (p) T1(value); }
对象的析构由destroy函数完成,该函数有两个版本:接受1个指针和接收两个迭代器的版本。接受1个指针的版本直接调用指针指向的对象的析构函数完成析构;接收两个迭代器的版本的destroy会判断迭代器指向的对象类型的析构函数是否是trivial的,若是,则什么也不做,若不是,则会遍历两个迭代器所指定的范围,逐个调用第1版本的destroy。这么做的目的主要是为了析构时的效率考虑。
下图为第1版本的destroy
//destroy()第一版本,接受一个指针 template <typename T> inline void destroy(T* point) { point->~T(); }
下图为第2版本的destroy
//有trivial destructor template <typename Iterator> inline void __destroy_aux(Iterator first, Iterator last, __true_type) {} //有non-trivial destructor template <typename Iterator> inline void __destroy_aux(Iterator first, Iterator last, __false_type) { for (; first < last; first++) destroy(&*first); //调用第一版本destroy() } //判断元素的值类型是否有trivial destructor template <typename Iterator, typename T> inline void __destroy(Iterator first, Iterator last, T* ) { typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor; __destroy_aux(first, last, trivial_destructor()); } //destroy()第二版本,接受两个迭代器 template <typename Iterator> inline void destroy(Iterator first, Iterator last) { __destroy(first, last, value_type(first)); }
其中,判断迭代器所指的对象类型,是通过iterator_traits模板结构体来判断的,利用了模板的参数推断功能,从而推断出该迭代器所指的对象类型。如下图所示:
//返回迭代器指向的对象类型 value_type* template <typename Iterator> inline typename iterator_traits<Iterator>::value_type* value_type(const Iterator&) { return static_cast<typename iterator_traits<Iterator>::value_type*>(NULL); }
//iterator traits template <typename Iterator> struct iterator_traits { typedef typename Iterator::iterator_category iterator_category; typedef typename Iterator::value_type value_type; typedef typename Iterator::difference_type difference_type; typedef typename Iterator::pointer pointer; typedef typename Iterator::reference reference; };