• 【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 }
  • 相关阅读:
    LeetCode(65):有效数字
    LeetCode(64):最小路径和
    物理Data Guard的日常维护
    Oracle Data Guard的配置
    SQL基础--完整性约束
    使用rman迁移数据库到异机
    Oracle的表空间和数据文件
    Oracle的控制文件
    Oracle重做日志文件
    RMAN的恢复篇
  • 原文地址:https://www.cnblogs.com/sunbines/p/9012501.html
Copyright © 2020-2023  润新知