最近仔細閱讀了下侯捷老師的《STL源碼剖析》的前三章內容:空間配置器、迭代器、traits技術,爲了增強理解和掌握,特參照源碼自實現Vector,如下對相關重點知識進行說明。
空間配置器方面的內容在以前的博客已進行詳細說明,查看->STL空間配置器解析和實現.html
(1)對象構造ios
(2)Destroy()函數的泛化和特化版本實現,主要體現對象T是否包含trivial construct框架
(3)迭代器範圍賦值ide
(4)迭代器範圍拷貝函數
template<class T1, class T2> void Construct(T1* p, const T2& value) { new (p) T1(value); // placement new;調用T1::T1(value) } template<class T> void Destroy(T* p) { p->~T(); p = NULL; } template<class ForwardIterator> void Destroy(ForwardIterator first, ForwardIterator last) { ForwardIterator iter = first; while (iter != last) { typedef typename TRAITS_DEFINE::iterator_traits<ForwardIterator>::value_type T; cout << typeid(T).name(); T p = (T)*iter; Destroy(&p); iter++; } } template<class ForwardIterator> void Destroy(ForwardIterator first, ForwardIterator last, TRAITS_DEFINE::__true_type) { ; } template<class ForwardIterator> void Destroy(ForwardIterator first, ForwardIterator last, TRAITS_DEFINE::__false_type) { for (; first<last; first++) { Destroy(&*first) } } template<class ForwardIterator, class T> void Destroy(ForwardIterator first, ForwardIterator last, T*) { typedef typename TRAITS_DEFINE::__type_traits<T>::has_trivial_destructor trivial_destructor; Destroy(first, last, trivial_destructor()); } template<class OutputIterator> OutputIterator uninitialized_fill_n_ex(OutputIterator iter, const size_type& nSize, const T& nValue) { for (size_t i = 0; i < nSize; i++) { *iter++ = nValue; } return iter; } void Fill_Initialize(const size_type& nSize, const T& nValue) { Iterator iter = data_allocator::Allocate(nSize); uninitialized_fill_n_ex(iter, nSize, nValue); Start = iter; Finish = Start + nSize; EndOfStorage = Finish; } template<class InputIterator, class OutputIterator> OutputIterator uninitialzed_copy_ex(InputIterator first, InputIterator last, OutputIterator dest) { for (; first != last; first++,dest++) { *dest = *first; } return dest; }
類型萃取實現的關鍵計數在於「模版特例化」,經過class template partial specialization的做用,不管是原生指針或class-type iterators,均可以讓外界方便地取其相應類別工具
原生指針不是class type,若是不是class type就沒法爲它定義內嵌型別。但模板特例化解決了該問題post
template<class T>測試
class C{...}; // 這個泛化版本容許(接受)T爲任何型別ui
template<class T>this
class C<T*>{...}; // 這個特化版本僅適用於「T爲原生指針」的狀況
type_traits類型萃取,判斷T類型中是否含有trivial construct,這樣在destroy函數的就能夠根據其作相應的處理
namespace TRAITS_DEFINE { template<class T> struct iterator_traits { typedef T value_type; }; template<class T> struct iterator_traits<T *> { typedef T value_type; }; struct __true_type{}; struct __false_type{}; template<class type> struct __type_traits { typedef __true_type this_dummy_must_be_first; typedef __false_type has_trivial_default_constructor; typedef __false_type has_trivial_copy_constructor; typedef __false_type has_trivial_assignment_operator; typedef __false_type has_trivial_destructor; typedef __false_type is_POD_type; }; template<> struct __type_traits<int> { typedef __true_type this_dummy_must_be_first; typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; }
typedef T& Reference; typedef T* Iterator; typedef T value_type; typedef size_t size_type; typedef CSimpleAlloc<value_type> data_allocator; // 自定義空間配置器 Iterator Start; Iterator Finish; Iterator EndOfStorage;
Vector():Start(NULL), Finish(NULL),EndOfStorage(NULL){
cout << "Vector()" << endl;
}
Vector(const size_type& nSize, const T& nValue)
{
Fill_Initialize(nSize, nValue);
}
explicit Vector(const size_type& nSize)
{
Fill_Initialize(nSize, T());
}
void Fill_Initialize(const size_type& nSize, const T& nValue) { Iterator iter = data_allocator::Allocate(nSize); uninitialized_fill_n_ex(iter, nSize, nValue); Start = iter; Finish = Start + nSize; EndOfStorage = Finish; }
void Deallocate() { if (Start) { data_allocator::Deallocate(Start, EndOfStorage-Start); } }
~Vector()
{
Destroy(Start, Finish);
Deallocate();
}
void Push(const T& Value) { if (Finish != EndOfStorage) { Construct(Finish, Value); // 全局函數 ++Finish; } else { // 容器已滿,需擴容 Insert_Aux(End(), Value); } } void Insert_Aux(Iterator position, const T& value) { if (Finish != EndOfStorage) { // 還有備用空間可用 Construct(Finish, *(Finish - 1)); ++Finish; T x_copy = value; //copy_backward(position, Finish - 2, Finish - 1); *position = x_copy; } else { // 已無備用空間 size_type nOldSize = Size(); size_type nNewSize = (nOldSize == 0) ? 1 : 2 * nOldSize; Iterator NewStart = data_allocator::Allocate(nNewSize); Iterator NewFinish = NewStart; try { NewFinish = uninitialzed_copy_ex(Start, position, NewStart); Construct(NewFinish, value); NewFinish++; } catch (...) { Destroy(NewStart, NewFinish); data_allocator::Deallocate(NewStart, nNewSize); throw; } Destroy(Begin(),End()); data_allocator::Deallocate(Start, EndOfStorage - Start); Start = NewStart; Finish = NewFinish; EndOfStorage = Start + nNewSize; } }
void Pop_Back() { if (!Empty()) { --Finish; Destroy(Finish); } }
Erase方法只能清空元素,但不能釋放空間
Iterator Erase(Iterator pos) { if (pos + 1 != Finish) { copy(pos + 1, Finish, pos); } --Finish; destroy(Finish); return pos; } Iterator Erase(Iterator first, Iterator last) { Iterator iter = uninitialzed_copy_ex(last, Finish, first); Destroy(iter, Finish); Finish = Finish - (last - first); return first; }
void Resize(size_type new_size, const T& x) { //若是新空間大小 小於size 就裁去多餘的 若是新空間大於size那麼就將這些插入. if (new_size < Size()) Erase(Begin() + new_size, End()); else { Iterator NewStart = data_allocator::Allocate(new_size); Iterator NewFinish = NewStart; try { NewFinish = uninitialzed_copy_ex(Start, Finish, NewStart); for (size_t i = 0; i < (new_size-Size()); i++) { *NewFinish++ = x; } } catch (...) { Destroy(NewStart, NewFinish); data_allocator::Deallocate(NewStart, new_size); throw; } Destroy(Begin(), End()); data_allocator::Deallocate(Start, EndOfStorage - Start); Start = NewStart; Finish = NewFinish; EndOfStorage = Start + new_size; } }
#pragma once #include "simple_alloc.h" #include <iostream> #include<memory> using namespace std; /* Construct和Destroy實現 */ namespace TRAITS_DEFINE { template<class T> struct iterator_traits { typedef T value_type; }; template<class T> struct iterator_traits<T *> { typedef T value_type; }; struct __true_type{}; struct __false_type{}; template<class type> struct __type_traits { typedef __true_type this_dummy_must_be_first; typedef __false_type has_trivial_default_constructor; typedef __false_type has_trivial_copy_constructor; typedef __false_type has_trivial_assignment_operator; typedef __false_type has_trivial_destructor; typedef __false_type is_POD_type; }; template<> struct __type_traits<int> { typedef __true_type this_dummy_must_be_first; typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; } // 內存管理工具 template<class T1, class T2> void Construct(T1* p, const T2& value) { new (p) T1(value); // placement new;調用T1::T1(value) } template<class T> void Destroy(T* p) { p->~T(); p = NULL; } template<class ForwardIterator> void Destroy(ForwardIterator first, ForwardIterator last) { ForwardIterator iter = first; while (iter != last) { typedef typename TRAITS_DEFINE::iterator_traits<ForwardIterator>::value_type T; cout << typeid(T).name(); T p = (T)*iter; Destroy(&p); iter++; } } template<class ForwardIterator> void Destroy(ForwardIterator first, ForwardIterator last, TRAITS_DEFINE::__true_type) { ; } template<class ForwardIterator> void Destroy(ForwardIterator first, ForwardIterator last, TRAITS_DEFINE::__false_type) { for (; first<last; first++) { Destroy(&*first) } } template<class ForwardIterator, class T> void Destroy(ForwardIterator first, ForwardIterator last, T*) { typedef typename TRAITS_DEFINE::__type_traits<T>::has_trivial_destructor trivial_destructor; Destroy(first, last, trivial_destructor()); } /* * 實現vector * vector基本操做:構造、resize、erase、push、pop */ template <typename T> class Vector { public: typedef T& Reference; typedef T* Iterator; typedef T value_type; typedef size_t size_type; typedef CSimpleAlloc<value_type> data_allocator; // 自定義空間配置器 Iterator Start; Iterator Finish; Iterator EndOfStorage; public: Vector():Start(NULL), Finish(NULL),EndOfStorage(NULL){ cout << "Vector()" << endl; } Vector(const size_type& nSize, const T& nValue) { Fill_Initialize(nSize, nValue); } explicit Vector(const size_type& nSize) { Fill_Initialize(nSize, T()); } ~Vector() { Destroy(Start, Finish); Deallocate(); } Iterator Begin(){return Start;} Iterator End(){return Finish;} size_type Size() const { return size_type(Finish - Start); } size_type Capacity() const { return size_type(EndOfStorage - Start); } bool Empty() { return Begin() == End(); } Reference operator[](const size_type& nIndex) { return *(start + n); } Reference Front(){ return *Start; } Reference Back(){ return *(--Finish); } void Push(const T& Value) { if (Finish != EndOfStorage) { Construct(Finish, Value); // 全局函數 ++Finish; } else { // 容器已滿,需擴容 Insert_Aux(End(), Value); } } void Pop_Back() { if (!Empty()) { --Finish; Destroy(Finish); } } void Print() { cout << "打印vector全部元素: "; Iterator iter = Start; while (iter != Finish) { cout << *iter << " "; iter++; } cout << endl; } Iterator Erase(Iterator pos) { if (pos + 1 != Finish) { copy(pos + 1, Finish, pos); } --Finish; destroy(Finish); return pos; } Iterator Erase(Iterator first, Iterator last) { Iterator iter = uninitialzed_copy_ex(last, Finish, first); Destroy(iter, Finish); Finish = Finish - (last - first); return first; } void Resize(size_type new_size, const T& x) { //若是新空間大小 小於size 就裁去多餘的 若是新空間大於size那麼就將這些插入. if (new_size < Size()) Erase(Begin() + new_size, End()); else { Iterator NewStart = data_allocator::Allocate(new_size); Iterator NewFinish = NewStart; try { NewFinish = uninitialzed_copy_ex(Start, Finish, NewStart); for (size_t i = 0; i < (new_size-Size()); i++) { *NewFinish++ = x; } } catch (...) { Destroy(NewStart, NewFinish); data_allocator::Deallocate(NewStart, new_size); throw; } Destroy(Begin(), End()); data_allocator::Deallocate(Start, EndOfStorage - Start); Start = NewStart; Finish = NewFinish; EndOfStorage = Start + new_size; } } void Clear() { Erase(Start, Finish); } private: void Deallocate() { if (Start) { data_allocator::Deallocate(Start, EndOfStorage-Start); } } void Insert_Aux(Iterator position, const T& value) { if (Finish != EndOfStorage) { // 還有備用空間可用 Construct(Finish, *(Finish - 1)); ++Finish; T x_copy = value; //copy_backward(position, Finish - 2, Finish - 1); *position = x_copy; } else { // 已無備用空間 size_type nOldSize = Size(); size_type nNewSize = (nOldSize == 0) ? 1 : 2 * nOldSize; Iterator NewStart = data_allocator::Allocate(nNewSize); Iterator NewFinish = NewStart; try { NewFinish = uninitialzed_copy_ex(Start, position, NewStart); Construct(NewFinish, value); NewFinish++; } catch (...) { Destroy(NewStart, NewFinish); data_allocator::Deallocate(NewStart, nNewSize); throw; } Destroy(Begin(),End()); data_allocator::Deallocate(Start, EndOfStorage - Start); Start = NewStart; Finish = NewFinish; EndOfStorage = Start + nNewSize; } } // 申請並填充內存 template<class OutputIterator> OutputIterator uninitialized_fill_n_ex(OutputIterator iter, const size_type& nSize, const T& nValue) { for (size_t i = 0; i < nSize; i++) { *iter++ = nValue; } return iter; } void Fill_Initialize(const size_type& nSize, const T& nValue) { Iterator iter = data_allocator::Allocate(nSize); uninitialized_fill_n_ex(iter, nSize, nValue); Start = iter; Finish = Start + nSize; EndOfStorage = Finish; } template<class InputIterator, class OutputIterator> OutputIterator uninitialzed_copy_ex(InputIterator first, InputIterator last, OutputIterator dest) { for (; first != last; first++,dest++) { *dest = *first; } return dest; } };
// 徹底解析STL空間配置器 /***** 一級配置區 ****************************/ // 1. 採用mallo/relloc/free申請和釋放內存 // 2. 處理內存申請失敗的處理 // (1)設置set_new_handle,若爲NULL拋出__THROW_BAD_ALLOC; // (2)嘗試重複申請 /**********************************************/ #pragma once class CFirstLevelAlloc; class CSecondLevelAlloc; #ifdef _CHUNK_ALLOC typedef CFirstLevelAlloc SelfAlloc; #else typedef CSecondLevelAlloc SelfAlloc; #endif typedef void(*CallBackFunc)(); class CFirstLevelAlloc { public: CFirstLevelAlloc(); static CallBackFunc m_CallBackFunc; static void* Allocate(size_t nSize); static void* Allocate(void *p, size_t nSize); static void Deallocate(void *p, size_t nSize = 0); static void SetCallBackHandle(CallBackFunc cb); private: static void* ReAllocate(size_t nSize); static void* ReAllocate(void *p, size_t nSize); }; enum {ALIGN = 8}; // 小型區塊的上調邊界 enum {MAX_BYTES = 128}; // 小型區塊的上限 enum {FREELISTNUM = MAX_BYTES/ALIGN}; // free-lists個數 // 空閒內存鏈表結構 union FreeList { union FreeList *pFreeList; char client_data[1]; }; class CSecondLevelAlloc { public: CSecondLevelAlloc(); static void* Allocate(size_t nSize); static void Deallocate(void *p, size_t nSize); static void SetCallBackHandle(CallBackFunc cb); private: static size_t FreeListIndex(int nBytes); // 根據區塊大小獲得freelist索引 static size_t Round_Up(int nBytes); // 將bytes按內存對齊上調至ALIGN的倍數 static char *ChunkAlloc(size_t nSize, int& nObjs); static void* Refill(size_t nSize); private: static FreeList *m_pFreeList[FREELISTNUM]; static char *m_pStartFree; static char *m_pEndFree; static size_t m_nHeapSize; };
#pragma once #include "alloc_define.h" template<typename T, typename Alloc = SelfAlloc> class CSimpleAlloc { public: static T* Allocate(size_t n) { if (n == 0) { return NULL; } return (T *)Alloc::Allocate(n * sizeof(T)); } static T* Allocate(void) { return (T *)Alloc::Allocate(sizeof(T)); } static void Deallocate(T *p, size_t n) { if (n != 0) { Alloc::Deallocate(p, n * sizeof(T)); } } static void Deallocate(T *p) { Alloc::Deallocate(p, sizeof(T)); } static void SetCallBackHandle(CallBackFunc cb) { Alloc::SetCallBackHandle(cb); } };
#include "stdio.h" #include "vector_define.h" #include<vector> using namespace std; void main() { cout << "Vector(const size_type& nSize, const T& nValue)測試:" << endl; Vector<int> vect1(4, 5); vect1.Print(); cout << "Vector()--Push()--Pop測試:" << endl; Vector<int> vect2; vect2.Push(1); vect2.Push(2); vect2.Push(3); vect2.Push(4); vect2.Print(); vect2.Pop_Back(); vect2.Print(); cout << "Iterator Erase(Iterator first, Iterator last)測試:" << endl; Vector<int>::Iterator iter1 = vect2.Begin(); Vector<int>::Iterator iter2 = vect2.End(); vect2.Erase(iter1, iter2); cout << "vect Size:" << vect2.Size() << endl; cout << "void Resize(size_type new_size, const T& x)測試:" << endl; vect2.Resize(2, 88); vect2.Print(); vect2.Resize(8, 66); vect2.Print(); }