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 }

 

posted @ 2015-03-31 21:35  bournet  阅读(921)  评论(0编辑  收藏  举报