STL源码剖析——全局函数construct(),destroy(),uninitialized_copy(),uninitialized_fill(),uninitialized_fill_n()

蔚落 2022-08-12 01:17 233阅读 0赞

前言

在STL中,内存处理时很关键的,特别是对于容器的实现,内存处理相当的重要。为了实现内存配置跟对象的构造行为分离开来,STL定义的五个基本全局函数,这五个全局函数中,贯穿在里面的基本上是Traits和__type_traits技术,之前看的时候不了解这两技术,因此,现在了解之后才来写这篇文章。有关Traits技术见前文《Traits编程技术》。

STL五个全局函数分别是:construct(),destroy(),uninitialized_copy(),uninitialized_fill(),uninitialized_fill_n();以下分别对这些函数进行讲解。

构造和析构基本工具:construct()和destroy()

在STL源码中,内存的配置和对象的构造与析构是分离开的,这两个函数实现对象的构造和析构,不进行分配内存空间,construct()函数在已分配内存上构造对象,具体实现看下面的源码及其解析:

  1. #ifndef __SGI_STL_INTERNAL_CONSTRUCT_H
  2. #define __SGI_STL_INTERNAL_CONSTRUCT_H
  3. #include <new.h>
  4. __STL_BEGIN_NAMESPACE
  5. // construct and destroy. These functions are not part of the C++ standard,
  6. // and are provided for backward compatibility with the HP STL. We also
  7. // provide internal names _Construct and _Destroy that can be used within
  8. // the library, so that standard-conforming pieces don't have to rely on
  9. // non-standard extensions.
  10. // Internal names
  11. template <class _T1, class _T2>
  12. //参数接受一个指针和一个初值
  13. inline void _Construct(_T1* __p, const _T2& __value) {
  14. new ((void*) __p) _T1(__value);/*这里是placement new;调用构造函数T1::T1(value)
  15. *将初值设定到指针所指的空间上
  16. */
  17. }
  18. template <class _T1>
  19. //这里只接受指针
  20. inline void _Construct(_T1* __p) {
  21. new ((void*) __p) _T1();//这里是placement new;调用默认构造函数T1::T1()
  22. }
  23. template <class _Tp>
  24. inline void _Destroy(_Tp* __pointer) {//第一个版本:接受一个指针
  25. __pointer->~_Tp();//调用对象析构函数,析构指针所指对象
  26. }
  27. template <class _ForwardIterator>
  28. /*第二个版本:接受两个迭代器first和last,自迭代器first开始到迭代器last结束,析构每个元素对象
  29. *为求最大效率,首先以__VALUE_TYPE()萃取出迭代器first的value_type
  30. *再利用__type_traits判断该型别是否trivial destructor*/
  31. inline void _Destroy(_ForwardIterator __first, _ForwardIterator __last) {
  32. __destroy(__first, __last, __VALUE_TYPE(__first));
  33. }
  34. template <class _ForwardIterator, class _Tp>
  35. inline void
  36. __destroy(_ForwardIterator __first, _ForwardIterator __last, _Tp*)
  37. {//利用__type_traits判断元素的数值型别是否有trivial destructor
  38. typedef typename __type_traits<_Tp>::has_trivial_destructor
  39. _Trivial_destructor;
  40. __destroy_aux(__first, __last, _Trivial_destructor());
  41. }
  42. template <class _ForwardIterator>
  43. /*若元素型别是有trivial destructor,就派送到该函数
  44. */
  45. inline void __destroy_aux(_ForwardIterator, _ForwardIterator, __true_type) {}
  46. template <class _ForwardIterator>
  47. void
  48. __destroy_aux(_ForwardIterator __first, _ForwardIterator __last, __false_type)
  49. {//若元素型别不具有trivial destructor,就派送到该函数
  50. for ( ; __first != __last; ++__first)
  51. destroy(&*__first);//这里最终还是调用了指针版的析构函数,析构每个元素对象
  52. }
  53. //以下是第二版析构函数针对内置类型的特化版
  54. inline void _Destroy(char*, char*) {}
  55. inline void _Destroy(int*, int*) {}
  56. inline void _Destroy(long*, long*) {}
  57. inline void _Destroy(float*, float*) {}
  58. inline void _Destroy(double*, double*) {}
  59. #ifdef __STL_HAS_WCHAR_T
  60. inline void _Destroy(wchar_t*, wchar_t*) {}
  61. #endif /* __STL_HAS_WCHAR_T */
  62. // --------------------------------------------------
  63. // Old names from the HP STL.
  64. template <class _T1, class _T2>
  65. inline void construct(_T1* __p, const _T2& __value) {
  66. _Construct(__p, __value);
  67. }
  68. template <class _T1>
  69. inline void construct(_T1* __p) {
  70. _Construct(__p);
  71. }
  72. template <class _Tp>//参数为指针版的析构函数
  73. inline void destroy(_Tp* __pointer) {
  74. _Destroy(__pointer);
  75. }
  76. template <class _ForwardIterator>//参数为迭代器版的析构函数
  77. inline void destroy(_ForwardIterator __first, _ForwardIterator __last) {
  78. _Destroy(__first, __last);
  79. }
  80. __STL_END_NAMESPACE
  81. #endif /* __SGI_STL_INTERNAL_CONSTRUCT_H */
  82. // Local Variables:
  83. // mode:C++
  84. // End:

未初始化空间的复制和初始化:uninitialized_copy(),uninitialized_fill()和uninitialized_fill_n()

在未初始化空间中,要对对象进行初始化时,会用到这些函数,该源码在文件中,具体实现看下面源码及其解析:

  1. #ifndef __SGI_STL_INTERNAL_UNINITIALIZED_H
  2. #define __SGI_STL_INTERNAL_UNINITIALIZED_H
  3. __STL_BEGIN_NAMESPACE
  4. // uninitialized_copy
  5. // Valid if copy construction is equivalent to assignment, and if the
  6. // destructor is trivial.
  7. template <class _InputIter, class _ForwardIter>
  8. /*该函数接受三个迭代器参数:迭代器first是输入的起始地址,
  9. *迭代器last是输入的结束地址,迭代器result是输出的起始地址
  10. *即把数据复制到[result,result+(last-first)]这个范围
  11. *为了提高效率,首先用__VALUE_TYPE()萃取出迭代器result的型别value_type
  12. *再利用__type_traits判断该型别是否为POD型别
  13. */
  14. inline _ForwardIter
  15. uninitialized_copy(_InputIter __first, _InputIter __last,
  16. _ForwardIter __result)
  17. {
  18. return __uninitialized_copy(__first, __last, __result,
  19. __VALUE_TYPE(__result));
  20. }
  21. template <class _InputIter, class _ForwardIter, class _Tp>
  22. inline _ForwardIter
  23. /*利用__type_traits判断该型别是否为POD型别*/
  24. __uninitialized_copy(_InputIter __first, _InputIter __last,
  25. _ForwardIter __result, _Tp*)
  26. {
  27. typedef typename __type_traits<_Tp>::is_POD_type _Is_POD;
  28. return __uninitialized_copy_aux(__first, __last, __result, _Is_POD());
  29. }
  30. template <class _InputIter, class _ForwardIter>
  31. _ForwardIter //若不是POD型别,就派送到这里
  32. __uninitialized_copy_aux(_InputIter __first, _InputIter __last,
  33. _ForwardIter __result,
  34. __false_type)
  35. {
  36. _ForwardIter __cur = __result;
  37. __STL_TRY {//这里加入了异常处理机制
  38. for ( ; __first != __last; ++__first, ++__cur)
  39. _Construct(&*__cur, *__first);//构造对象,必须是一个一个元素的构造,不能批量
  40. return __cur;
  41. }
  42. __STL_UNWIND(_Destroy(__result, __cur));//析构对象
  43. }
  44. template <class _InputIter, class _ForwardIter>
  45. inline _ForwardIter //若是POD型别,就派送到这里
  46. __uninitialized_copy_aux(_InputIter __first, _InputIter __last,
  47. _ForwardIter __result,
  48. __true_type)
  49. {
  50. /*调用STL的算法copy()
  51. *函数原型:template< class InputIt, class OutputIt >
  52. * OutputIt copy( InputIt first, InputIt last, OutputIt d_first );
  53. */
  54. return copy(__first, __last, __result);
  55. }
  56. //下面是针对char*,wchar_t* 的uninitialized_copy()特化版本
  57. inline char* uninitialized_copy(const char* __first, const char* __last,
  58. char* __result) {
  59. /* void* memmove( void* dest, const void* src, std::size_t count );
  60. * dest指向输出的起始地址
  61. * src指向输入的其实地址
  62. * count要复制的字节数
  63. */
  64. memmove(__result, __first, __last - __first);
  65. return __result + (__last - __first);
  66. }
  67. inline wchar_t*
  68. uninitialized_copy(const wchar_t* __first, const wchar_t* __last,
  69. wchar_t* __result)
  70. {
  71. memmove(__result, __first, sizeof(wchar_t) * (__last - __first));
  72. return __result + (__last - __first);
  73. }
  74. // Valid if copy construction is equivalent to assignment, and if the
  75. // destructor is trivial.
  76. template <class _ForwardIter, class _Tp>
  77. /*若是POD型别,则调用此函数
  78. */
  79. inline void
  80. __uninitialized_fill_aux(_ForwardIter __first, _ForwardIter __last,
  81. const _Tp& __x, __true_type)
  82. {
  83. /*函数原型:template< class ForwardIt, class T >
  84. * void fill( ForwardIt first, ForwardIt last, const T& value );
  85. */
  86. fill(__first, __last, __x);
  87. }
  88. template <class _ForwardIter, class _Tp>
  89. /*若不是POD型别,则调用此函数
  90. */
  91. void
  92. __uninitialized_fill_aux(_ForwardIter __first, _ForwardIter __last,
  93. const _Tp& __x, __false_type)
  94. {
  95. _ForwardIter __cur = __first;
  96. __STL_TRY {
  97. for ( ; __cur != __last; ++__cur)
  98. _Construct(&*__cur, __x);
  99. }
  100. __STL_UNWIND(_Destroy(__first, __cur));
  101. }
  102. template <class _ForwardIter, class _Tp, class _Tp1>
  103. //用__type_traits技术判断该型别是否
  104. POD型别
  105. inline void __uninitialized_fill(_ForwardIter __first,
  106. _ForwardIter __last, const _Tp& __x, _Tp1*)
  107. {
  108. typedef typename __type_traits<_Tp1>::is_POD_type _Is_POD;
  109. __uninitialized_fill_aux(__first, __last, __x, _Is_POD());
  110. }
  111. template <class _ForwardIter, class _Tp>
  112. /*该函数接受三个参数:
  113. *迭代器first指向欲初始化的空间起始地址
  114. *迭代器last指向欲初始化的空间结束地址
  115. *x表示初值
  116. *首先利用__VALUE_TYPE()萃取出迭代器first的型别value_type
  117. *然后用__type_traits技术判断该型别是否为POD型别
  118. */
  119. inline void uninitialized_fill(_ForwardIter __first,
  120. _ForwardIter __last,
  121. const _Tp& __x)
  122. {
  123. __uninitialized_fill(__first, __last, __x, __VALUE_TYPE(__first));
  124. }
  125. // Valid if copy construction is equivalent to assignment, and if the
  126. // destructor is trivial.
  127. template <class _ForwardIter, class _Size, class _Tp>
  128. inline _ForwardIter
  129. /*若是POD型别,则调用此函数
  130. */
  131. __uninitialized_fill_n_aux(_ForwardIter __first, _Size __n,
  132. const _Tp& __x, __true_type)
  133. {
  134. /*调用STL算法
  135. *原型:template< class OutputIt, class Size, class T >
  136. * void fill_n( OutputIt first, Size count, const T& value );
  137. * template< class OutputIt, class Size, class T >
  138. * OutputIt fill_n( OutputIt first, Size count, const T& value );
  139. */
  140. return fill_n(__first, __n, __x);
  141. }
  142. template <class _ForwardIter, class _Size, class _Tp>
  143. _ForwardIter
  144. /*若不是POD型别,则调用此函数
  145. */
  146. __uninitialized_fill_n_aux(_ForwardIter __first, _Size __n,
  147. const _Tp& __x, __false_type)
  148. {
  149. _ForwardIter __cur = __first;
  150. __STL_TRY {
  151. for ( ; __n > 0; --__n, ++__cur)
  152. _Construct(&*__cur, __x);
  153. return __cur;
  154. }
  155. __STL_UNWIND(_Destroy(__first, __cur));
  156. }
  157. template <class _ForwardIter, class _Size, class _Tp, class _Tp1>
  158. inline _ForwardIter
  159. //用__type_traits技术判断该型别是否为POD型别
  160. __uninitialized_fill_n(_ForwardIter __first, _Size __n, const _Tp& __x, _Tp1*)
  161. {
  162. typedef typename __type_traits<_Tp1>::is_POD_type _Is_POD;
  163. //_Is_POD()判断value_type是否为POD型别
  164. return __uninitialized_fill_n_aux(__first, __n, __x, _Is_POD());
  165. }
  166. template <class _ForwardIter, class _Size, class _Tp>
  167. inline _ForwardIter
  168. /*该函数接受三个参数:
  169. *迭代器first指向欲初始化的空间起始地址
  170. *n表示欲初始化空间大小
  171. *x表示初值
  172. *首先利用__VALUE_TYPE()萃取出迭代器first的型别value_type
  173. *然后用__type_traits技术判断该型别是否为POD型别
  174. */
  175. uninitialized_fill_n(_ForwardIter __first, _Size __n, const _Tp& __x)
  176. {
  177. //__VALUE_TYPE(__first)萃取出first的型别value_type
  178. return __uninitialized_fill_n(__first, __n, __x, __VALUE_TYPE(__first));
  179. }
  180. __STL_END_NAMESPACE
  181. #endif /* __SGI_STL_INTERNAL_UNINITIALIZED_H */
  182. // Local Variables:
  183. // mode:C++
  184. // End:

总结

在这个五个全局函数中,我们可以看到,基本上是Traits和__type_traits技术的作用,方便内存处理,并且提高效率。

发表评论

表情:
评论列表 (有 0 条评论,233人围观)

还没有评论,来说两句吧...

相关阅读

    相关 STL剖析】Sort算法

    前言:sort算法必须拿出来单独将,因为它是STL所有算法中最复杂最庞大的一个,就像我肯定会把copy算法单独列出来一样,这两个算法太重要了。 提示:STL算法特点是,前两个

    相关 STL剖析--vector

    vector容器概述       vector的数据安排以及操作方式,与array非常相似。两者的唯一区别在于空间的运用的灵活性。array是静态空间,一旦配置了就不能改变

    相关 STL剖析1

    stl概论 stl以抽象概念为主题而非以实际类为主的结构,形成了一个严谨的接口标准。在此接口之下,任何组件都有最大的独立性,并以所谓迭代器胶合起来,或以所谓配接器互相配接,或