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 }