StrVec类的设计
【题目描述】:我们将实现标准库vector类的一个简化版本,我们所做的一个简化是不使用模板,我们类只用于string,因此,它被命名为StrVec。
1 #include<iostream> 2 #include<string> 3 #include<memory> 4 using namespace std; 5 6 class StrVec { 7 public: 8 StrVec(): elements(nullptr), first_free(nullptr), cap(nullptr) {} 9 StrVec(const StrVec &); 10 StrVec& operator=(const StrVec&); 11 ~StrVec() { free(); }; 12 13 StrVec(StrVec &&s) noexcept; 14 StrVec& opearator=(StrVec &&rhs) noexcept; 15 16 void push_back (const string&); 17 size_t size() const { return first_free - elements; } 18 size_t capacity() const { return cap - elements; } 19 string *begin() const { return elements; } 20 string *end() const { return first_free; } 21 22 private: 23 static allocator<string> alloc; 24 void chk_n_alloc() { if (size() == capacity()) reallocate(); } 25 pair<string*, string*> alloc_n_copy(const string*, const string *); 26 void free(); 27 void reallocate(); 28 string *elements; //指向数组首元素的指针 29 string *first_free; //指向数组第一个空闲元素的指针 30 string *cap; //指向数组尾后位置的指针 31 }; 32 33 StrVec::StrVec(const StrVec &s) 34 { 35 auto newdata = alloc_n_copy(s.begin(), s.end()); 36 elements = newdata.first; 37 first_free = cap = newdata.second; 38 } 39 40 StrVec& StrVec::operator=(const StrVec &rhs) 41 { 42 auto data = alloc_n_copy(rhs.begin(), rhs.end()); 43 free(); 44 elements = data.first; 45 first_free = cap = newdata.second; 46 return *this; 47 } 48 49 void StrVec::free() 50 { 51 if (elements) 52 { 53 for (auto p = first_free; p != elements; ) 54 alloc.destroy(--p); 55 alloc.deallocate(elements, cap - elements); 56 } 57 } 58 59 pair<string *, string *> StrVec::alloc_n_copy(const string *b, const string *e) 60 { 61 auto data = alloc.allocate(e - b); 62 return { data, uninitialized_copy(b, e, data) }; 63 } 64 65 void StrVec::push_back(const string& s) 66 { 67 chk_n_alloc(); 68 alloc.construct(first_free++, s); 69 } 70 71 void StrVec::reallocate() 72 { 73 auto newcapacity = size() ? 2 * size() : 1; 74 auto newdata = alloc.allocate(newcapacity); 75 auto dest = newdata; 76 auto elem = elements; //原对象的elements指针 77 for (size_t i = 0; i != size(); ++i) 78 alloc.construct(dest++, std::move(*elem++)); 79 free(); 80 elements = newdata; 81 first_free = dest; 82 cap = elements + newcapacity; 83 } 84 85 StrVec::StrVec(StrVec &&s) noexcept 86 : elements(s.elements), first_free(s.first_free), cap(s.cap) 87 { 88 s.elements = s.first_free = cap = nulllptr; 89 } 90 91 StrVec& StrVec::StrVec(StrVec &&s) noexcept 92 { 93 if (this = &s) 94 { 95 free(); 96 elemens = rhs.elements; 97 first_free = .frhsirst_free; 98 cap = rhs.cap; 99 rhs.elements = srhs.first_free = rhs.cap = nullptr; 100 } 101 return *this; 102 }
3.5节练习
• 编写标准库string类的简化版本,命名为string。
1 #include<iostream> 2 #include<memory> 3 #include<cstring> 4 #include<initializer_list> 5 using namespace std; 6 7 class String { 8 friend String operator+(const String&, const String&); 9 friend String add(const String&, const String&); 10 friend ostream &operator<<(std::ostream&, const String&); 11 friend ostream &print(std::ostream&, const String&); 12 13 public: 14 String():sz(0), p(nullptr) {}; 15 String(const char *cp): sz(strlen(cp)), p(p.allocate(sz)) { uninitialized_copy(cp, cp + sz, p)} 16 String(const String &s): sz(s.sz), p(a.allocate(sz)) { uninitialized_copy(s.p, s.p + sz, p)} 17 String(size_t n, char c): sz(n), p(a.allocate(n)) {uninitialized_fill_n(p, n, t)} 18 ~String() noexcept { if (p) a.deallocate(p, sz); } 19 20 String &operator=(const String &); 21 String &operator=(const char*); 22 String &operator=(char); 23 String &operator=(initializer_list<char>); 24 25 26 const char *begin() { return p; } 27 const char *begin() const { return p; } 28 const char *end() { return p + sz; } 29 const char *end() const { return p + sz; } 30 size_t size() const { return sz; } 31 void swap(String &s); 32 33 private: 34 static allocator<char> a; 35 size_t sz; 36 char *p; 37 }; 38 39 /***********************************************************************************/ 40 ostream &operator<<(ostream &os, const string &s) 41 { 42 return print(os, rhs); 43 } 44 45 ostream &print(ostream &os, const string &s) 46 { 47 auto p = s.begin(); 48 while(p != s.end()) 49 os << *p++; 50 return os; 51 } 52 53 string add(const string &lhs, const string &rhs) 54 { 55 string ret; 56 ret.sz = lhs.size() + rhs.size(); 57 ret.p = a.allocate(ret.sz); 58 uninitialized_copy(lhs.begin(), lhs.end(),ret.p); 59 uninitialized_copy(rhs.begin(), rhs.end(), ret.p + lhs.sz); 60 return ret; 61 } 62 63 string operator+(const string &lhs, const string &rhs) 64 { 65 return add(lhs, rhs); 66 } 67 /************************************************************************************/ 68 69 String &String::operator=(const String &rhs) 70 { 71 auto newp = a.allocator(rhs.sz); 72 uninitlized_copy(rhs.p, rhs.p + rhs.ze, newp); 73 if (p) 74 a.deallocate(p, sz); 75 p = newp; 76 sz = rhs.sz; 77 return *this; 78 } 79 80 String &String::operator=(const char *cp) 81 { 82 if(p) 83 a.deallocate(p, sz); 84 p = a.allocate(sz = strlen(cp)); 85 uninitialzied_copy(cp, cp + sz, p); 86 return *this; 87 } 88 89 String &String::operator=(char c) 90 { 91 if(p) 92 a.deallocate(p, sz); 93 p = a.allocate(sz = 1); 94 *p = c; 95 return *this; 96 } 97 98 String& string::operator=(initializer_list<char> il) 99 { 100 if(p) 101 a.deallocate(p, sz); 102 p = a.llocate(il.size()); 103 uninitialized_copy(il.begin(), il.end(), p); 104 return *this; 105 } 106 107 /***************************************************************************************/ 108 109 void string::swap(String &s) 110 { 111 auto tmp = p; 112 p = s.p; 113 s.p = tmp; 114 auto cnt = sz; 115 sz = s.sz; 116 s.sz = cnt; 117 } 118 119 void swap(String &s1, String &s2) 120 { 121 s1.swap(s2); 122 123 124 String make_plural(size_t ctr, const String &, const String &) 125 { 126 return (ctr != 1) ? add(word, ending) : word; 127 }