模拟实现STL库
Posted 请叫我小小兽
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模拟实现STL库相关的知识,希望对你有一定的参考价值。
最近在复习STL,感觉再看的时候比刚开始学的时候通透很多。以前模拟实现了一个STL库,最近复习完又重构了一遍。代码放出来以供后面学习。如果有写的不好的地方欢迎大家批评指正。
STL_List.h
1 #pragma once 2 #include"STL_Iterator.h" 3 4 template<class T> 5 struct _List_Node 6 { 7 _List_Node* _prev; 8 _List_Node* _next; 9 T _data; 10 _List_Node() 11 { 12 13 } 14 _List_Node(const T& x) 15 :_data(x) 16 , _prev(NULL) 17 , _next(NULL) 18 { 19 20 } 21 }; 22 23 template<class T, class Ref, class Ptr> 24 struct _List_Iterator 25 { 26 typedef BidirectionalIterator_tag IteratorCategory; 27 typedef _List_Iterator<T, T&, T*> Iterator; 28 typedef T ValueType; 29 typedef T& Reference; 30 typedef T* Pointer; 31 typedef _List_Node<T> *LinkType; 32 typedef _List_Iterator<T, Ref, Ptr> Self; 33 typedef int DifferenceType; 34 LinkType _node; 35 36 _List_Iterator() 37 { 38 39 } 40 _List_Iterator(LinkType x) 41 :_node(x) 42 { 43 } 44 Reference operator*() 45 { 46 return _node->_data; 47 } 48 Pointer operator->() 49 { 50 return &(_node->_data); 51 } 52 Iterator operator++() 53 { 54 _node = _node->_next; 55 return *this; 56 } 57 Iterator operator++(int) 58 { 59 Iterator tmp; 60 tmp = *this; 61 _node = _node->_next; 62 return tmp; 63 } 64 65 Iterator operator--() 66 { 67 _node = _node->_prev; 68 return *this; 69 } 70 Iterator operator--(int) 71 { 72 Iterator tmp = *this; 73 _node = _node->_prev; 74 return tmp; 75 } 76 77 bool operator!=(const Self& x) 78 { 79 return _node != x._node; 80 } 81 82 bool operator==(const Self& x) 83 { 84 return _node == x._node; 85 } 86 87 88 }; 89 90 template<class T, class Alloc = Alloc> 91 class List 92 { 93 public: 94 typedef _List_Node<T>* LinkType; 95 typedef _List_Iterator<T, T&, T*> Iterator; 96 typedef SimpleAlloc<_List_Node<T>, Alloc> ListNodeAllocator; 97 98 List() 99 { 100 _node = new _List_Node<T>(); 101 _node->_next = _node; 102 _node->_prev = _node; 103 } 104 ~List() 105 { 106 Destory(Begin(), End()); 107 Iterator it = Begin(); 108 while (it != End()) 109 { 110 ListNodeAllocator::Deallocate(it._node); 111 } 112 } 113 114 115 Iterator Begin() 116 { 117 return _node->_next; 118 } 119 120 Iterator End() 121 { 122 return _node; 123 } 124 125 126 127 128 Iterator Insert(Iterator pos, const T& x) 129 { 130 LinkType prev = pos._node->_prev; 131 LinkType tmp = ListNodeAllocator::Allocate(); 132 Construct(tmp, x); 133 //LinkType tmp = new _List_Node<T>(x); 134 prev->_next = tmp; 135 pos._node->_prev = tmp; 136 tmp->_next = pos._node; 137 tmp->_prev = prev; 138 return tmp; 139 } 140 141 142 void PushBack(const T& x) 143 { 144 Insert(End(), x); 145 } 146 147 148 void PushFront(const T& x) 149 { 150 Insert(Begin, x); 151 } 152 153 154 //reverse 155 //remove 156 //empty 157 //size 158 //unique 159 //merge 160 protected: 161 LinkType _node; 162 }; 163 164 165 void TestList() 166 { 167 List<int> l; 168 l.PushBack(1); 169 l.PushBack(2); 170 l.PushBack(3); 171 l.PushBack(4); 172 l.PushBack(5); 173 174 List<int>::Iterator it; 175 List<int>::Iterator begin = l.Begin(); 176 List<int>::Iterator end = l.End(); 177 for (it = l.Begin(); it != l.End(); it++) 178 { 179 cout << *it << " "; 180 } 181 cout << "Distance" << Distance(begin, end) << endl; 182 }
STL_Vector.h
1 #pragma once 2 #include<cassert> 3 #include"STL_Iterator.h" 4 #include"STL_Alloc.h" 5 #include"STL_Construct.h" 6 #include"STL_Uninittialized.h" 7 8 template<class T, class Alloc = Alloc> 9 class Vector 10 { 11 typedef T ValueType; 12 typedef T& Reference; 13 typedef T* Pointer; 14 typedef int DifferenceType; 15 public: 16 typedef ValueType * Iterator; 17 typedef RandomAccessIterator_tag IteratorCategory; 18 typedef SimpleAlloc<T, Alloc> DataAlloc; 19 20 21 22 Iterator Begin() { return Start; } 23 Iterator End() { return Finish; } 24 25 Vector() 26 :Start(NULL) 27 , Finish(NULL) 28 , EndOfStorage(NULL) 29 { 30 31 } 32 Vector(size_t n, const T& value) 33 { 34 Start = new T[n]; 35 Finish = Start + n; 36 EndOfStorage = Finish; 37 } 38 ~Vector() 39 { 40 Destory(Start, Finish); 41 DataAlloc::Deallocate(Start, Size()); 42 } 43 44 45 46 47 /*void Insert(Iterator Position,size_t n,const ValueType& x) 48 { 49 if (n != 0) 50 { 51 if (size_t(EndOfStorage - Finish) > n) 52 { 53 size_t Elems_After = Finish - Position; 54 Iterator OldFinish = Finish; 55 if (Elems_After > n) 56 { 57 Finish += n; 58 Copy_Backward(Position, OldFinish - n, OldFinish); 59 while (n-- > 0) 60 { 61 *(Position++) = x; 62 } 63 } 64 else 65 { 66 int tmp = n - Elems_After; 67 while (tmp-- > 0) 68 { 69 *(Finish++) = x; 70 } 71 tmp = OldFinish - Position; 72 for (int i = 0; i < tmp; ++i) 73 { 74 *(Finish++) = *(Position + i); 75 } 76 while (n-- > 0) 77 { 78 *(Position++) = x; 79 } 80 } 81 } 82 else 83 { 84 ExpandCapacity(); 85 Insert(Position, n, x); 86 } 87 } 88 }*/ 89 void Push_Back(const T& x) 90 { 91 ExpandCapacity(); 92 Construct(Finish, x); 93 Finish++; 94 95 } 96 void Pop_Back() 97 { 98 assert(Size()); 99 Destory(Finish);//ÓбØҪô£¿£¿ 100 --Finish; 101 } 102 size_t Size() 103 { 104 return (Finish - Start); 105 } 106 107 bool Empty() 108 { 109 return Beign == End; 110 } 111 112 Iterator Erase(Iterator pos) 113 { 114 Iterator begin = pos; 115 wihle(begin + 1 != Finish) 116 { 117 *begin = *(beign + 1); 118 } 119 --Finish; 120 return pos; 121 } 122 123 124 125 protected: 126 127 void Copy_Backward(Iterator Position, Iterator first, Iterator last) 128 { 129 while (first != Position - 1) 130 { 131 *(last--) = *(first--); 132 } 133 134 } 135 void ExpandCapacity() 136 { 137 if (Finish == EndOfStorage) 138 { 139 size_t size = Size(); 140 size_t curLength = EndOfStorage - Start; 141 size_t newLength = 2 * curLength + 3; 142 T *tmp = DataAlloc::Allocate(newLength); 143 if (Start) 144 { 145 UninitializedCopy(Start, Start + size, tmp); 146 } 147 Destory(Start, Finish); 148 DataAlloc::Deallocate(Start, EndOfStorage - Start); 149 150 Start = tmp; 151 Finish = Start + Size(); 152 EndOfStorage = Start + newLength; 153 154 /* Iterator newStart = new T[newLength]; 155 Iterator it = Begin(); 156 for (int i = 0; i < Size(); ++i) 157 { 158 newStart[i] = Start[i]; 159 } 160 Destory(); 161 Start = newStart; 162 Finish = Start + curLength; 163 EndOfStorage = Start + newLength;*/ 164 } 165 } 166 //void Destory() 167 //{ 168 // delete[] Start; 169 // Start = NULL; 170 // Finish = NULL; 171 // EndOfStorage = NULL; 172 //} 173 protected: 174 Iterator Start; 175 Iterator Finish; 176 Iterator EndOfStorage; 177 }; 178 179 180 void TestVector() 181 { 182 Vector<int> v; 183 v.Push_Back(1); 184 v.Push_Back(2); 185 v.Push_Back(3); 186 v.Push_Back(4); 187 v.Push_Back(5); 188 Vector<int>::Iterator cur; 189 for (cur = v.Begin(); cur != v.End(); cur++) 190 { 191 cout << *cur << " "; 192 } 193 }
vector的数据安排和数组非常相似。两者的差别在于数组是静态空间,一旦配置了就不能改变,而vector是动态空间,随着元素的加入,他的内部会自行扩充空间(自行扩充不是在原有空间上 续接新空间,因为无法保证原空间之后还有可供配置的空间,所以他会重新开辟一块原大小二倍的空间,然后将原来的数据拷贝过来,然后在原内容之后构造新元素,并释放原有空间)。一旦vector旧有空间满载,内部只是扩充一个元素的空间实为不智,因为配置新空间,数据移动,释放原空间成本很高,应该加入某种未雨绸缪的考虑,在STL中就是空间扩大原来的二倍。
数组和链表的区别:
- 数组是将元素在内存中连续存放,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素。但是如果要在数组中增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放在其中。同样的道理,如果想删除一个元素,同样需要移动大量元素去填掉被移动的元素。如果应用需要快速访问数据,很少或不插入和删除元素,就应该用数组。
- 链表恰好相反,链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起。比如:上一个元素有个指针指到下一个元素,以此类推,直到最后一个元素。如果要访问链表中一个元素,需要从第一个元素开始,一直找到需要的元素位置。但是增加和删除一个元素对于链表数据结构就非常简单了,只要修改元素中的指针就可以了。如果应用需要经常插入和删除元素你就需要用链表数据结构了。
*C++语言中可以用数组处理一组数据类型相同的数据,但不允许动态定义数组的大小,即在使用数组之前必须确定数组的大小。而在实际应用中,用户使用数组之前有时无法准确确定数组的大小,只能将数组定义成足够大小,这样数组中有些空间可能不被使用,从而造成内存空间的浪费。链表是一种常见的数据组织形式,它采用动态分配内存的形式实现。需要时可以用new分配内存空间,不需要时用delete将已分配的空间释放,不会造成内存空间的浪费。
(1) 从逻辑结构角度来看
a, 数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。
b,链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项)
(2)从内存存储角度来看
a,(静态)数组从栈中分配空间, 对于程序员方便快速,但自由度小。
b, 链表从堆中分配空间, 自由度大但申请管理比较麻烦.
STL_Uninitialized.h
1 #pragma once 2 #include"STL_Iterator.h" 3 #include"TypeTraits.h" 4 #include"STL_Construct.h" 5 #include"STL_Iterator.h" 6 #include<memory.h> 7 8 template <class InputIterator, class ForwardIterator> 9 inline ForwardIterator 10 __UninitializedCopyAux(InputIterator first, InputIterator last, 11 ForwardIterator result, 12 __TrueType) { 13 return copy(first, last, result); 14 } 15 16 17 template <class InputIterator, class ForwardIterator> 18 ForwardIterator 19 __UninitializedCopyAux(InputIterator first, InputIterator last, 20 ForwardIterator result, 21 __FalseType) { 22 ForwardIterator cur = result; 23 24 for (; first != last; ++first, ++cur) 25 Construct(&*cur, *first); 26 return cur; 27 } 28 29 template <class InputIterator, class ForwardIterator, class T> 30 inline ForwardIterator __UninitializedCopy(InputIterator first, InputIterator last, 31 ForwardIterator result, T*) 32 { 33 typedef typename __TypeTraits<T>::IsPODType IsPOD; 34 return __UninitializedCopyAux(first, last, result, IsPOD()); 35 } 36 37 38 template <class InputIterator, class ForwardIterator> 39 inline ForwardIterator UninitializedCopy(InputIterator first, InputIterator last, 40 ForwardIterator result) { 41 return __UninitializedCopy(first, last, result, ValueType(result)); 42 } 43 44 inline char* UninitializedCopy(const char* first, const char* last, 45 char* result) { 46 memmove(result, first, last - first); 47 return result + (last - first); 48 } 49 50 inline wchar_t* UninitializedCopy(const wchar_t* first, const wchar_t* last, 51 wchar_t* result) { 52 memmove(result, first, sizeof(wchar_t)* (last - first)); 53 return result + (last - first); 54 }
STL_Construct.h
1 #pragma once 2 3 #include"TypeTraits.h" 4 5 6 template<class T> 7 inline void Destory(T *pointer) 8 { 9 pointer->~T(); 10 } 11 12 template<class T1, class T2> 13 inline void Construct(T1 *p, const T2& value) 14 { 15 new(p)T1(value); 16 } 17 18 19 template<class ForwardIterator> 20 inline void __DestoryAux(ForwardIterator first, ForwardIterator last, __FalseType) 21 { 22 for (; first < last; ++first) 23 { 24 Destory(&*first); 25以上是关于模拟实现STL库的主要内容,如果未能解决你的问题,请参考以下文章