allocator类的使用 - 实现自己的vector
allocator类是一个模板,它提供类型化的内存分配以及对象构造与撤销。allocator类将内存分配与对象构造分开。当allocator对象分配内存时,它分配适当大小并排列成保存给定类型对象的空间。但是,它分配的内存时未构造的,allocator用户必须分别construct和destroy放置在该内存中的对象。
下面通过实现一个动态数组说明allocator的使用。
1 #ifndef MYVECTOR_H 2 #define MYVECTOR_H 3 #include <memory> 4 #include <cstddef> 5 using namespace std; 6 7 template <class T> 8 class Vector 9 { 10 public: 11 Vector(): elements(0), first_free(0), end(0) {} 12 void push_back(const T&); 13 void reserve(const size_t capa); 14 15 //调整Vector大小,使其能容纳n个元素 16 //如果n小于Vector当前大小,则删除多余元素 17 //否则,添加采用值初始化的新元素 18 void resize(const size_t n); 19 20 //调整Vector大小,使其能容纳n个元素 21 //所有新添加元素值都为t 22 void resize(const size_t n, const T& t); 23 24 //下表操作符 25 T& operator[] (const size_t n); 26 const T& operator[] (const size_t) const; 27 28 //返回Vector大小 29 size_t size() 30 { 31 return first_free-elements; 32 } 33 34 //返回Vector容量 35 size_t capacity() 36 { 37 return end-elements; 38 } 39 40 private: 41 //用于获取未构造内存的对象 42 static std::allocator<T> alloc; 43 //获取更多空间并复制现有元素 44 void reallocate(); 45 46 //指向第一个元素的指针 47 T* elements; 48 //指向第一个自由元素的指针 49 T* first_free; 50 //指向数组末端的下一个元素位置的指针 51 T* end; 52 }; 53 54 #endif
1 #include "Vector.hpp" 2 3 template <class T> 4 allocator<T> Vector<T>::alloc; 5 6 template <class T> 7 void Vector<T>::push_back(const T& t) 8 { 9 if (first_free == end) 10 //已用完所分配空间 11 //获取更多空间,并复制现有元素至新分配空间 12 reallocate(); 13 alloc.construct(first_free, t); 14 ++first_free; 15 } 16 17 template <class T> 18 void Vector<T>::reallocate() 19 { 20 //计算当前大小,并分配两倍于当前元素数的空间 21 ptrdiff_t size = first_free - elements; 22 ptrdiff_t newcapacity = 2*max(size, 1); 23 24 //分配空间以保存newcapacity个T类的元素 25 T* newelements = alloc.allocate(newcapacity); 26 27 //在新空间构造现有元素的副本 28 uninitialized_copy(elements, first_free, newelements); 29 30 //逆序撤销旧元素 31 for (T *p = first_free; p != elements; ) 32 alloc.destroy(--p); 33 34 //不能用0值指针调用deallocate 35 if (elements) 36 //释放保存元素的内存 37 alloc.deallocate(elements, end-elements); 38 39 //使数据结构指向新元素 40 elements = newelements; 41 first_free = elements + size; 42 end = elements + newcapacity; 43 } 44 45 template <class T> 46 void Vector<T>::reserve(const size_t capa) 47 { 48 //计算当前数组大小 49 size_t size = first_free-elements; 50 //分配可保存capa个T类型元素的空间 51 T *newelements = alloc.allocate(capa); 52 //在新空间构造现有元素的副本 53 if (size <= capa) 54 uninitialized_copy(elements, first_free, newelements); 55 else 56 //如果capa小于原来数组的size,则去掉多余的元素 57 uninitialized_copy(elements, elements+capa, newelements); 58 59 //逆序撤销旧元素 60 for (T *p = first_free; p != elements; ) 61 alloc.destroy(--p); 62 63 if (elements) 64 //释放旧元素所占内存 65 alloc.deallocate(elements, end-elements); 66 67 //使数据结构指向新元素 68 elements = newelements; 69 first_free = elements + min(size, capa); 70 end = elements + capa; 71 } 72 73 template <class T> 74 void Vector<T>::resize(const size_t n) 75 { 76 //计算当前大小及容量 77 size_t size = first_free - elements; 78 size_t capacity = end - elements; 79 80 if (n > capacity) 81 { 82 reallocate(); 83 uninitialized_fill(elements+size, elements+n, T()); 84 } 85 else if (n > size) 86 { 87 uninitialized_fill(elements+size, elements+n, T()); 88 } 89 else 90 { 91 for (T *p = first_free; p != elements; ) 92 alloc.destroy(--p); 93 } 94 first_free = elements + n; 95 } 96 97 template <class T> 98 void Vector<T>::resize(const size_t n, const T& t) 99 { 100 size_t size = first_free - elements; 101 size_t capacity = end - elements; 102 103 if (n > capacity) 104 { 105 reallocate(); 106 uninitialized_fill(elements+size, elements+n, t); 107 } 108 else if (n > size) 109 { 110 uninitialized_fill(elements+size, elements+n, t); 111 } 112 else 113 { 114 for (T *p = first_free; p != elements; ) 115 alloc.destroy(--p); 116 } 117 first_free = elements+n; 118 } 119 120 template <class T> 121 T& Vector<T>::operator[] (const size_t index) 122 { 123 return elements[index]; 124 } 125 126 template <class T> 127 const T& Vector<T>::operator[] (const size_t index) const 128 { 129 return elements[index]; 130 }
1 #include <iostream> 2 #include <string> 3 #include "Vector.hpp" 4 #include "Vector.cpp" 5 using namespace std; 6 7 8 int main() 9 { 10 Vector<int> ivec; 11 for (size_t i = 0; i != 8; ++i) 12 { 13 ivec.push_back(i); 14 cout << ivec[i] << "\t"; 15 } 16 cout << endl; 17 18 cout << ivec.size() << "\t" << ivec.capacity() << endl; 19 ivec.reserve(50); 20 cout << ivec.size() << "\t" << ivec.capacity() << endl; 21 ivec.resize(20); 22 for (size_t i = 0; i != 20; ++i) 23 cout << ivec[i] << "\t"; 24 cout << endl; 25 26 cout << ivec.size() << "\t" << ivec.capacity() << endl; 27 cout << ivec[2] << "\t" << ivec[10] << endl; 28 29 30 return 0; 31 }