class StrVec
{
private:
static allocator<string> alloc; //静态变量,用来分配元素
string *elements; //首元素
string *first_free; //指向第一个空闲的元素
string *cap; //指向数组尾后位置的元素
//检查内存是否够用
void chk_n_alloc()
{
if (size() == capacity()) reallocate();
}
//创造一个从b到e的内存,并赋值,返回首元素和末元素之后的位置
pair<string*, string*> alloc_n_copy(const string*, const string*);
void free(); //销毁元素并释放内存
void reallocate(); //获得更多内存,并拷贝已有元素
public:
StrVec() :elements(nullptr), first_free(nullptr), cap(nullptr) {};
StrVec(const StrVec&); //拷贝构造函数
StrVec &operator=(const StrVec&);
~StrVec();
void push_back(const string&);
size_t size() { return first_free - elements; };
size_t capacity() { return cap - elements; };
string *begin() const { return elements; };
string *end() const { return first_free; };
};
void StrVec::push_back(const string& s)
{
chk_n_alloc();
alloc.construct(first_free++,s);
}
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::free()
{
if (elements)
{
for (auto p = first_free; p != elements;)
alloc.destroy(--p);
alloc.deallocate(elements, cap - elements);
}
}
StrVec::StrVec(const StrVec &s)
{
auto newdata = alloc_n_copy(s.begin(), s.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::reallocate()
{
auto newcapacity = size() ? 2 * size() : 1;
auto newdata = alloc.allocate(newcapacity);
auto dest = newdata; //首元素
auto elem = elements;
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, std::move(*elements++));
free();
elements = newdata;
first_free = dest;
cap = elements + newcapacity;
}
下面是拷贝控制的应用
using namespace std;
class Folder
{
private:
set<Message*> msg;
public:
Folder() {};
Folder &operator=(const Folder &f)
{
msg = f.msg;
}
void addMsg(Message *m)
{
msg.insert(m);
}
void remMsg(Message *m)
{
if(msg.find(m)!=msg.end()) msg.erase(m);
}
};
class Message
{
friend class Folder;
friend void swap(Message &lhs, Message&rhs);
private:
string contents; //实际消息文本
set<Folder*> folders; //包含文本Message的folder
//拷贝构造函数,拷贝赋值运算符和析构函数所使用的工具函数
//讲文本Message添加到Folder中
void add_to_Folders(const Message&);
void remove_from_Folders();
public:
//folders被隐式初始化为空集合
explicit Message(const string &str = "") :contents(str) {};
//拷贝控制成员,用来管理指向本Message的指针
Message(const Message&);
Message &operator=(const Message&);
~Message();
//从给定Folder集合中添加/删除本Message
void save(Folder&);
void remove(Folder&);
//向给定的folders中加入folder或删除指定的folder
void Add(Folder&);
void REM(Folder&);
};
void Message::Add(Folder& f)
{
folders.insert(&f);
}
void Message::REM(Folder& f)
{
if (folders.find(&f) != folders.end()) folders.erase(&f);
}
void Message::save(Folder& f)
{
folders.insert(&f);
f.addMsg(this);
}
void Message::remove(Folder& f)
{
folders.erase(&f);
f.remMsg(this);
}
void Message::add_to_Folders(const Message &m)
{
for (auto f : m.folders)
f->addMsg(this);
}
Message::Message(const Message &m):contents(m.contents),folders(m.folders)
{
add_to_Folders(m); //拷贝构造函数,会将副本也添加到之前的folders中
}
void Message::remove_from_Folders()
{
for (auto f : folders)
f->remMsg(this);
}
Message::~Message()
{
remove_from_Folders(); //要保证删除此message,之前所有存储它的folder的记录也得删除
//set 和string 自带析构函数
}
Message& Message::operator=(const Message &rhs)
{
remove_from_Folders();
contents = rhs.contents;
folders = rhs.folders;
add_to_Folders(rhs);
return *this;
}
void swap(Message &lhs, Message&rhs)
{
using std::swap;
for (auto f : lhs.folders)
f->remMsg(&lhs);
for (auto f : rhs.folders)
f->remMsg(&rhs);
swap(lhs.contents, rhs.contents);
swap(lhs.folders, lhs.folders);
for (auto f : lhs.folders)
f->addMsg(&lhs);
for (auto f : rhs.folders)
f->addMsg(&rhs);
}