1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
| class StrVec { public: StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) { } StrVec(const StrVec&); StrVec& operator=(const StrVec&); ~StrVec();
void push_back(const std::string&); size_t size() const { return first_free - elements; } size_t capacity() const { return cap - elements; } std::string* begin() const { return elements; } std::string* end() const { return first_free; }
void reserve(size_t new_cap); void resize(size_t count); void resize(size_t count, const std::string&);
private: std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*); void free(); void chk_n_alloc() { if (size() == capacity()) reallocate(); } void reallocate(); void alloc_n_move(size_t new_cap);
private: std::string* elements; std::string* first_free; std::string* cap; std::allocator<std::string> alloc; };
void StrVec::push_back(const std::string& s) { chk_n_alloc(); alloc.construct(first_free++, s); }
std::pair<std::string*, std::string*> StrVec::alloc_n_copy(const std::string* b, const std::string* e) { auto data = alloc.allocate(e - b); return{ data, std::uninitialized_copy(b, e, data) }; }
void StrVec::free() { if (elements) { for (auto p = first_free; p != elements;) alloc.destroy(--p); alloc.deallocate(elements, cap - elements); } }
StrVec::StrVec(const StrVec& rhs) { auto newdata = alloc_n_copy(rhs.begin(), rhs.end()); elements = newdata.first; first_free = cap = newdata.second; }
StrVec::~StrVec() { free(); }
StrVec& StrVec::operator = (const StrVec& rhs) { auto data = alloc_n_copy(rhs.begin(), rhs.end()); free(); elements = data.first; first_free = cap = data.second; return *this; }
void StrVec::alloc_n_move(size_t new_cap) { auto newdata = alloc.allocate(new_cap); auto dest = newdata; auto elem = elements; for (size_t i = 0; i != size(); ++i) alloc.construct(dest++, std::move(*elem++)); free(); elements = newdata; first_free = dest; cap = elements + new_cap; }
void StrVec::reallocate() { auto newcapacity = size() ? 2 * size() : 1; alloc_n_move(newcapacity); }
void StrVec::reserve(size_t new_cap) { if (new_cap <= capacity()) return; alloc_n_move(new_cap); }
void StrVec::resize(size_t count) { resize(count, std::string()); }
void StrVec::resize(size_t count, const std::string& s) { if (count > size()) { if (count > capacity()) reserve(count * 2); for (size_t i = size(); i != count; ++i) alloc.construct(first_free++, s); } else if (count < size()) { while (first_free != elements + count) alloc.destroy(--first_free); } }
|