### 前言
? 在STL中,內存處理時很關鍵的,特別是對于容器的實現,內存處理相當的重要。為了實現內存配置跟對象的構造行為分離開來,STL定義的五個基本全局函數,這五個全局函數中,貫穿在里面的基本上是Traits和__type_traits技術,之前看的時候不了解這兩技術,因此,現在了解之后才來寫這篇文章。有關Traits技術見前文[《](http://blog.csdn.net/chenhanzhun/article/details/39230529)[Traits](http://blog.csdn.net/chenhanzhun/article/details/39230529)[編程技術》](http://blog.csdn.net/chenhanzhun/article/details/39230529)。
? ? ?STL五個全局函數分別是:construct(),destroy(),uninitialized_copy(),uninitialized_fill(),uninitialized_fill_n();以下分別對這些函數進行講解。
### 構造和析構基本工具:construct()和destroy()
? 在STL源碼<stl_construct.h>中,內存的配置和對象的構造與析構是分離開的,這兩個函數實現對象的構造和析構,不進行分配內存空間,construct()函數在已分配內存上構造對象,具體實現看下面的源碼及其解析:
~~~
#ifndef __SGI_STL_INTERNAL_CONSTRUCT_H
#define __SGI_STL_INTERNAL_CONSTRUCT_H
#include <new.h>
__STL_BEGIN_NAMESPACE
// construct and destroy. These functions are not part of the C++ standard,
// and are provided for backward compatibility with the HP STL. We also
// provide internal names _Construct and _Destroy that can be used within
// the library, so that standard-conforming pieces don't have to rely on
// non-standard extensions.
// Internal names
template <class _T1, class _T2>
//參數接受一個指針和一個初值
inline void _Construct(_T1* __p, const _T2& __value) {
new ((void*) __p) _T1(__value);/*這里是placement new;調用構造函數T1::T1(value)
*將初值設定到指針所指的空間上
*/
}
template <class _T1>
//這里只接受指針
inline void _Construct(_T1* __p) {
new ((void*) __p) _T1();//這里是placement new;調用默認構造函數T1::T1()
}
template <class _Tp>
inline void _Destroy(_Tp* __pointer) {//第一個版本:接受一個指針
__pointer->~_Tp();//調用對象析構函數,析構指針所指對象
}
template <class _ForwardIterator>
/*第二個版本:接受兩個迭代器first和last,自迭代器first開始到迭代器last結束,析構每個元素對象
*為求最大效率,首先以__VALUE_TYPE()萃取出迭代器first的value_type
*再利用__type_traits判斷該型別是否trivial destructor*/
inline void _Destroy(_ForwardIterator __first, _ForwardIterator __last) {
__destroy(__first, __last, __VALUE_TYPE(__first));
}
template <class _ForwardIterator, class _Tp>
inline void
__destroy(_ForwardIterator __first, _ForwardIterator __last, _Tp*)
{//利用__type_traits判斷元素的數值型別是否有trivial destructor
typedef typename __type_traits<_Tp>::has_trivial_destructor
_Trivial_destructor;
__destroy_aux(__first, __last, _Trivial_destructor());
}
template <class _ForwardIterator>
/*若元素型別是有trivial destructor,就派送到該函數
*/
inline void __destroy_aux(_ForwardIterator, _ForwardIterator, __true_type) {}
template <class _ForwardIterator>
void
__destroy_aux(_ForwardIterator __first, _ForwardIterator __last, __false_type)
{//若元素型別不具有trivial destructor,就派送到該函數
for ( ; __first != __last; ++__first)
destroy(&*__first);//這里最終還是調用了指針版的析構函數,析構每個元素對象
}
//以下是第二版析構函數針對內置類型的特化版
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*) {}
#ifdef __STL_HAS_WCHAR_T
inline void _Destroy(wchar_t*, wchar_t*) {}
#endif /* __STL_HAS_WCHAR_T */
// --------------------------------------------------
// Old names from the HP STL.
template <class _T1, class _T2>
inline void construct(_T1* __p, const _T2& __value) {
_Construct(__p, __value);
}
template <class _T1>
inline void construct(_T1* __p) {
_Construct(__p);
}
template <class _Tp>//參數為指針版的析構函數
inline void destroy(_Tp* __pointer) {
_Destroy(__pointer);
}
template <class _ForwardIterator>//參數為迭代器版的析構函數
inline void destroy(_ForwardIterator __first, _ForwardIterator __last) {
_Destroy(__first, __last);
}
__STL_END_NAMESPACE
#endif /* __SGI_STL_INTERNAL_CONSTRUCT_H */
// Local Variables:
// mode:C++
// End:
~~~
### 未初始化空間的復制和初始化:uninitialized_copy(),uninitialized_fill()和uninitialized_fill_n()
? 在未初始化空間中,要對對象進行初始化時,會用到這些函數,該源碼在文件<stl_uninitialized.h>中,具體實現看下面源碼及其解析:
~~~
#ifndef __SGI_STL_INTERNAL_UNINITIALIZED_H
#define __SGI_STL_INTERNAL_UNINITIALIZED_H
__STL_BEGIN_NAMESPACE
// uninitialized_copy
// Valid if copy construction is equivalent to assignment, and if the
// destructor is trivial.
template <class _InputIter, class _ForwardIter>
/*該函數接受三個迭代器參數:迭代器first是輸入的起始地址,
*迭代器last是輸入的結束地址,迭代器result是輸出的起始地址
*即把數據復制到[result,result+(last-first)]這個范圍
*為了提高效率,首先用__VALUE_TYPE()萃取出迭代器result的型別value_type
*再利用__type_traits判斷該型別是否為POD型別
*/
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
/*利用__type_traits判斷該型別是否為POD型別*/
__uninitialized_copy(_InputIter __first, _InputIter __last,
_ForwardIter __result, _Tp*)
{
typedef typename __type_traits<_Tp>::is_POD_type _Is_POD;
return __uninitialized_copy_aux(__first, __last, __result, _Is_POD());
}
template <class _InputIter, class _ForwardIter>
_ForwardIter //若不是POD型別,就派送到這里
__uninitialized_copy_aux(_InputIter __first, _InputIter __last,
_ForwardIter __result,
__false_type)
{
_ForwardIter __cur = __result;
__STL_TRY {//這里加入了異常處理機制
for ( ; __first != __last; ++__first, ++__cur)
_Construct(&*__cur, *__first);//構造對象,必須是一個一個元素的構造,不能批量
return __cur;
}
__STL_UNWIND(_Destroy(__result, __cur));//析構對象
}
template <class _InputIter, class _ForwardIter>
inline _ForwardIter //若是POD型別,就派送到這里
__uninitialized_copy_aux(_InputIter __first, _InputIter __last,
_ForwardIter __result,
__true_type)
{
/*調用STL的算法copy()
*函數原型:template< class InputIt, class OutputIt >
* OutputIt copy( InputIt first, InputIt last, OutputIt d_first );
*/
return copy(__first, __last, __result);
}
//下面是針對char*,wchar_t* 的uninitialized_copy()特化版本
inline char* uninitialized_copy(const char* __first, const char* __last,
char* __result) {
/* void* memmove( void* dest, const void* src, std::size_t count );
* dest指向輸出的起始地址
* src指向輸入的其實地址
* count要復制的字節數
*/
memmove(__result, __first, __last - __first);
return __result + (__last - __first);
}
inline 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);
}
// Valid if copy construction is equivalent to assignment, and if the
// destructor is trivial.
template <class _ForwardIter, class _Tp>
/*若是POD型別,則調用此函數
*/
inline void
__uninitialized_fill_aux(_ForwardIter __first, _ForwardIter __last,
const _Tp& __x, __true_type)
{
/*函數原型:template< class ForwardIt, class T >
* void fill( ForwardIt first, ForwardIt last, const T& value );
*/
fill(__first, __last, __x);
}
template <class _ForwardIter, class _Tp>
/*若不是POD型別,則調用此函數
*/
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));
}
template <class _ForwardIter, class _Tp, class _Tp1>
//用__type_traits技術判斷該型別是否
為POD型別
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>
/*該函數接受三個參數:
*迭代器first指向欲初始化的空間起始地址
*迭代器last指向欲初始化的空間結束地址
*x表示初值
*首先利用__VALUE_TYPE()萃取出迭代器first的型別value_type
*然后用__type_traits技術判斷該型別是否為POD型別
*/
inline void uninitialized_fill(_ForwardIter __first,
_ForwardIter __last,
const _Tp& __x)
{
__uninitialized_fill(__first, __last, __x, __VALUE_TYPE(__first));
}
// Valid if copy construction is equivalent to assignment, and if the
// destructor is trivial.
template <class _ForwardIter, class _Size, class _Tp>
inline _ForwardIter
/*若是POD型別,則調用此函數
*/
__uninitialized_fill_n_aux(_ForwardIter __first, _Size __n,
const _Tp& __x, __true_type)
{
/*調用STL算法
*原型:template< class OutputIt, class Size, class T >
* void fill_n( OutputIt first, Size count, const T& value );
* template< class OutputIt, class Size, class T >
* OutputIt fill_n( OutputIt first, Size count, const T& value );
*/
return fill_n(__first, __n, __x);
}
template <class _ForwardIter, class _Size, class _Tp>
_ForwardIter
/*若不是POD型別,則調用此函數
*/
__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, class _Tp1>
inline _ForwardIter
//用__type_traits技術判斷該型別是否為POD型別
__uninitialized_fill_n(_ForwardIter __first, _Size __n, const _Tp& __x, _Tp1*)
{
typedef typename __type_traits<_Tp1>::is_POD_type _Is_POD;
//_Is_POD()判斷value_type是否為POD型別
return __uninitialized_fill_n_aux(__first, __n, __x, _Is_POD());
}
template <class _ForwardIter, class _Size, class _Tp>
inline _ForwardIter
/*該函數接受三個參數:
*迭代器first指向欲初始化的空間起始地址
*n表示欲初始化空間大小
*x表示初值
*首先利用__VALUE_TYPE()萃取出迭代器first的型別value_type
*然后用__type_traits技術判斷該型別是否為POD型別
*/
uninitialized_fill_n(_ForwardIter __first, _Size __n, const _Tp& __x)
{
//__VALUE_TYPE(__first)萃取出first的型別value_type
return __uninitialized_fill_n(__first, __n, __x, __VALUE_TYPE(__first));
}
__STL_END_NAMESPACE
#endif /* __SGI_STL_INTERNAL_UNINITIALIZED_H */
// Local Variables:
// mode:C++
// End:
~~~
### 總結
? 在這個五個全局函數中,我們可以看到,基本上是Traits和__type_traits技術的作用,方便內存處理,并且提高效率。
- 前言
- 空間配置器
- Traits編程技術
- STL源碼剖析——迭代器
- 全局函數construct(),destroy(),uninitialized_copy(),uninitialized_fill(),uninitialized_fill_n()
- 序列容器之vector
- list容器的排序算法sort()
- 序列容器之list
- 序列容器之deque
- 容器配接器之stack
- 容器配接器之queue
- 容器配接器之priority_queue
- 最大堆heap
- 單向鏈表slist
- RB-Tree(紅黑樹)
- 關聯容器之set
- stl_pair.h學習
- 關聯容器之map
- 關聯容器之multiset
- 關聯容器之multimap
- 散列表hashtable
- stl_hash_fun.h學習
- 關聯容器之hash_set
- 關聯容器之hash_multiset
- 關聯容器之hash_map
- 關聯容器之hash_multimap
- 數值算法stl_numeric.h
- stl_relops.h學習
- 基本算法stl_algobase.h
- STL算法之set集合算法
- STL算法stl_algo.h
- STL算法之sort排序算法
- STL算法之find查找算法
- STL算法之merge合并算法
- STL算法之remove刪除算法
- STL算法之permutation排列組合
- STL函數對象