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

时间:2023-03-09 06:54:18
【C++ Primer 第13章】5. 动态内存管理类

StrVec类的设计

【题目描述】:我们将实现标准库vector类的一个简化版本,我们所做的一个简化是不使用模板,我们类只用于string,因此,它被命名为StrVec。

 #include<iostream>
#include<string>
#include<memory>
using namespace std; class StrVec {
public:
StrVec(): elements(nullptr), first_free(nullptr), cap(nullptr) {}
StrVec(const StrVec &);
StrVec& operator=(const StrVec&);
~StrVec() { free(); }; StrVec(StrVec &&s) noexcept;
StrVec& opearator=(StrVec &&rhs) noexcept; void push_back (const string&);
size_t size() const { return first_free - elements; }
size_t capacity() const { return cap - elements; }
string *begin() const { return elements; }
string *end() const { return first_free; } private:
static allocator<string> alloc;
void chk_n_alloc() { if (size() == capacity()) reallocate(); }
pair<string*, string*> alloc_n_copy(const string*, const string *);
void free();
void reallocate();
string *elements; //指向数组首元素的指针
string *first_free; //指向数组第一个空闲元素的指针
string *cap; //指向数组尾后位置的指针
}; StrVec::StrVec(const StrVec &s)
{
auto newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
first_free = cap = newdata.second;
} StrVec& StrVec::operator=(const StrVec &rhs)
{
auto data = alloc_n_copy(rhs.begin(), rhs.end());
free();
elements = data.first;
first_free = cap = newdata.second;
return *this;
} void StrVec::free()
{
if (elements)
{
for (auto p = first_free; p != elements; )
alloc.destroy(--p);
alloc.deallocate(elements, cap - elements);
}
} pair<string *, string *> StrVec::alloc_n_copy(const string *b, const string *e)
{
auto data = alloc.allocate(e - b);
return { data, uninitialized_copy(b, e, data) };
} void StrVec::push_back(const string& s)
{
chk_n_alloc();
alloc.construct(first_free++, s);
} void StrVec::reallocate()
{
auto newcapacity = size() ? * size() : ;
auto newdata = alloc.allocate(newcapacity);
auto dest = newdata;
auto elem = elements; //原对象的elements指针
for (size_t i = ; i != size(); ++i)
alloc.construct(dest++, std::move(*elem++));
free();
elements = newdata;
first_free = dest;
cap = elements + newcapacity;
} StrVec::StrVec(StrVec &&s) noexcept
: elements(s.elements), first_free(s.first_free), cap(s.cap)
{
s.elements = s.first_free = cap = nulllptr;
} StrVec& StrVec::StrVec(StrVec &&s) noexcept
{
if (this = &s)
{
free();
elemens = rhs.elements;
first_free = .frhsirst_free;
cap = rhs.cap;
rhs.elements = srhs.first_free = rhs.cap = nullptr;
}
return *this;
}

3.5节练习

• 编写标准库string类的简化版本,命名为string。

 #include<iostream>
#include<memory>
#include<cstring>
#include<initializer_list>
using namespace std; class String {
friend String operator+(const String&, const String&);
friend String add(const String&, const String&);
friend ostream &operator<<(std::ostream&, const String&);
friend ostream &print(std::ostream&, const String&); public:
String():sz(), p(nullptr) {};
String(const char *cp): sz(strlen(cp)), p(p.allocate(sz)) { uninitialized_copy(cp, cp + sz, p)}
String(const String &s): sz(s.sz), p(a.allocate(sz)) { uninitialized_copy(s.p, s.p + sz, p)}
String(size_t n, char c): sz(n), p(a.allocate(n)) {uninitialized_fill_n(p, n, t)}
~String() noexcept { if (p) a.deallocate(p, sz); } String &operator=(const String &);
String &operator=(const char*);
String &operator=(char);
String &operator=(initializer_list<char>); const char *begin() { return p; }
const char *begin() const { return p; }
const char *end() { return p + sz; }
const char *end() const { return p + sz; }
size_t size() const { return sz; }
void swap(String &s); private:
static allocator<char> a;
size_t sz;
char *p;
}; /***********************************************************************************/
ostream &operator<<(ostream &os, const string &s)
{
return print(os, rhs);
} ostream &print(ostream &os, const string &s)
{
auto p = s.begin();
while(p != s.end())
os << *p++;
return os;
} string add(const string &lhs, const string &rhs)
{
string ret;
ret.sz = lhs.size() + rhs.size();
ret.p = a.allocate(ret.sz);
uninitialized_copy(lhs.begin(), lhs.end(),ret.p);
uninitialized_copy(rhs.begin(), rhs.end(), ret.p + lhs.sz);
return ret;
} string operator+(const string &lhs, const string &rhs)
{
return add(lhs, rhs);
}
/************************************************************************************/ String &String::operator=(const String &rhs)
{
auto newp = a.allocator(rhs.sz);
uninitlized_copy(rhs.p, rhs.p + rhs.ze, newp);
if (p)
a.deallocate(p, sz);
p = newp;
sz = rhs.sz;
return *this;
} String &String::operator=(const char *cp)
{
if(p)
a.deallocate(p, sz);
p = a.allocate(sz = strlen(cp));
uninitialzied_copy(cp, cp + sz, p);
return *this;
} String &String::operator=(char c)
{
if(p)
a.deallocate(p, sz);
p = a.allocate(sz = );
*p = c;
return *this;
} String& string::operator=(initializer_list<char> il)
{
if(p)
a.deallocate(p, sz);
p = a.llocate(il.size());
uninitialized_copy(il.begin(), il.end(), p);
return *this;
} /***************************************************************************************/ void string::swap(String &s)
{
auto tmp = p;
p = s.p;
s.p = tmp;
auto cnt = sz;
sz = s.sz;
s.sz = cnt;
} void swap(String &s1, String &s2)
{
s1.swap(s2); String make_plural(size_t ctr, const String &, const String &)
{
return (ctr != ) ? add(word, ending) : word;
}