【C++ Primer 第13章】5. 动态内存管理类

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 }
原文地址:https://www.cnblogs.com/sunbines/p/9012501.html