模拟实现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 }
View Code

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 }
View Code
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 }
View Code

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库的主要内容,如果未能解决你的问题,请参考以下文章

C++STL第一篇:string类介绍及模拟实现

C++STL之string类的使用和实现

C++STL第二篇:vector类的介绍及模拟实现

C++STL第二篇:vector类的介绍及模拟实现

STL-vector 模板类 模拟实现

STL中string类基本概念及模拟实现