stl_construct.h文件提供构造和析构对象最基本的全局函数。
从代码上看,此文件中的构造函数将指定对象拷贝到指定指针中,没有申请新空间,只是在对原有地址空间基础上做扩充,而析构函数也仅仅调用了非平凡对象的析构函数,并未直接释放内存。文件提供的全局函数只负责对象内存配置后的构造行为和内存释放前的析构行为。
最基本的placement new构造对象函数,使用在现有的地址空间上进行拷贝构造的操作,在预分配的内存上创建对象(缺省情况下new是失效的)。
template <class T1, class T2> inline void construct(T1* p, const T2& value) { new (p) T1(value); //placement new } |
全局析构函数,仅仅调用对象的析构函数,并未释放内存
template <class T> inline void destroy(T* pointer) { pointer->~T(); //调用指针pointer指向对象的析构函数,并没有释放内存 } |
全局半开半闭区间[first, last)析构函数
template <class ForwardIterator> inline void destroy(ForwardIterator first, ForwardIterator last) { __destroy(first, last, value_type(first)); //???目前没搞清楚这个参数作用 } template <class ForwardIterator, class T> inline void __destroy(ForwardIterator first, ForwardIterator last, T*) { // 关于typename 在此处作用说明如下 typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor; __destroy_aux(first, last, trivial_destructor()); } |
//该元素的析构函数是trivial的,则什么也不做 template <class ForwardIterator> inline void __destroy_aux(ForwardIterator, ForwardIterator, __true_type) { //no-op }
//该元素的析构函数是non-trivial的,则依序调用其析构函数 template <class ForwardIterator> inline void __destroy_aux(ForwardIterator first, ForwardIterator last, __false_type) { for ( ; first < last; ++first) destroy(&*first); } |
typename说明:
typename关键字在此处的用意是向编译器表明trivial_destructor是一个类型而不是:
Ø 静态数据成员
Ø 静态成员函数
Ø 嵌套类型
查看__type_traits<T>::has_trivial_destructor定义发现其为一个模板结构体,里面重声明了很多__false_type类型,并且接下来定义了所有c/c++内置类型的特化版本。这些特化版本与原始模板结构体的不同在于,原始模板声明的类型全为struct __false_type, 而特化版本中申明的类型为struct __true_type。比如
__STL_TEMPLATE_NULL struct __type_traits<char> { typedef __true_type has_trivial_default_constructor; //标识char对象有平凡默认构造函数 typedef __true_type has_trivial_copy_constructor; //标识char对象有平凡拷贝构造函数 typedef __true_type has_trivial_assignment_operator; //标识char对象有平凡复制运算 typedef __true_type has_trivial_destructor; //标识char对象有平凡析构函数 typedef __true_type is_POD_type; //标识char对象是一个POD类型(通俗的讲,一个类或结构体通过二进制拷贝后还能保持其数据不变,那么它就是一个POD类型。) }; |
于是回到__destroy(3)函数,当T确定后,trivial_destructor类型也确定了,若T类型属于c/c++内建对象,则trivial_destructor类型为__true_type,于是调用函数
__destroy_aux(..., __true_type)析构对象即什么都不做,否则调用
__destroy_aux(..., __false_type)逐个调用半开半闭集中对象的析构函数。所以__destroy(3)函数利用了函数重载机制巧妙的避开对内建对象的析构。