1 #include<iostream>
2 #include<string>
3 #include<memory>
4 #include<utility>
5 using namespace std;
6
7 class StrVec {
8 public:
9 StrVec():element(nullptr),first_free(nullptr),cap(nullptr){} // 默认构造函数
10 StrVec(const StrVec&); //拷贝构造函数
11 StrVec &operator=(const StrVec&); //赋值拷贝运算符
12 ~StrVec();
13
14 void push_back(const string&);
15
16 size_t size() const {
17 return first_free - element;
18 }
19 size_t capacity()const {
20 return cap - element;
21 }
22 string *begin() const {
23 return element;
24 }
25 string *end()const {
26 return first_free;
27 }
28
29 private:
30 static allocator<string> alloc;
31
32 void chk_n_alloc() {
33 if (size() == capacity())
34 reallocate();
35 }
36 pair<string*, string*> alloc_n_copy(const string*, const string*); // 用于被copy控制成员调用
37
38 void free();
39 void reallocate(); //获得另一块更大的内存(释放原有内存)并拷贝已有元素 (实现的是标准库vector的内存分配机制)
40 string *element; // 数组首地址
41 string *first_free;
42 string *cap;
43
44 };
45
46
47 void StrVec::push_back(const string& s)
48 {
49 chk_n_alloc();
50 alloc.construct(first_free++, s);
51 }
52
53 pair<string*, string*> StrVec::alloc_n_copy(const string *b, const string *e)
54 {
55 auto data = alloc.allocate(e - b);
56 return { data,uninitialized_copy(b,e,data) };
57 }
58
59
60 void StrVec::free()
61 {
62 if (element) {
63 for (auto p = first_free; p != element;)
64 alloc.destroy(--p);
65 alloc.deallocate(element, cap - element);
66 }
67 }
68
69
70 StrVec::StrVec(const StrVec& s)
71 {
72 //调用alloc_n_copy分配空间以容纳与s中一样多的元素
73 auto newdate = alloc_n_copy(s.begin(), s.end());
74 element = newdate.first;
75 first_free = newdate.second;
76 }
77
78 StrVec::~StrVec()
79 {
80 free();
81 }
82
83 StrVec& StrVec::operator=(const StrVec& rhs)
84 {
85 auto data = alloc_n_copy(rhs.begin(), rhs.end());
86 free();
87 element = data.first;
88 first_free = cap = data.second;
89 return *this;
90 }
91
92 //在一个新的,更大的string数组分配内存
93 //在内存空间的前一部分构造对象,保存现有元素
94 //销毁原内存中的元素,并释放这块内存
95 void StrVec::reallocate()
96 {
97 //分配当前大小两倍的内存空间
98 auto newCapacity = size() ? 2 * size() : 1;
99 auto newdata = alloc.allocate(newCapacity);
100
101 auto dest = newdata; // 新内存首地址
102 auto elem = element; // 旧内存首地址
103
104 for (size_t i = 0; i != size(); ++i)
105 alloc.construct(dest++, std::move(*elem++)); // 因为vector重新分配内存,会将原来的数据销毁,没必要拷贝,这里使用移动拷贝来提高效率
106 free();
107 element = newdata;
108 first_free = dest;
109 cap = element + newCapacity;
110
111 }