习题13-31
#include <iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
class HasPtr
{
friend void swap(HasPtr&, HasPtr&);
public:
HasPtr(const string &s=string()):
ps(new string(s)),i(0){}
HasPtr(const HasPtr &p):
ps(new string(*p.ps)),i(p.i){}
HasPtr &operator=(const HasPtr&);
HasPtr &operator=(const string &);
string &operator*();
bool operator<(const HasPtr&)const;
~HasPtr();
private:
string *ps;
int i;
};
HasPtr::~HasPtr()
{
delete ps;
}
inline HasPtr &HasPtr::operator=(const HasPtr &rhs)
{
auto newps = new string(*rhs.ps);
delete ps;
ps = newps;
i = rhs.i;
return *this;
}
HasPtr& HasPtr::operator=(const string &rhs)
{
*ps = rhs;
return *this;
}
string &HasPtr::operator*()
{
return *ps;
}
inline void swap(HasPtr &lhs, HasPtr &rhs)
{
using std::swap;
cout << "交换" << *lhs.ps << "和" << *rhs.ps << endl;
swap(lhs.ps, rhs.ps);
swap(lhs.i, rhs.i);
}
bool HasPtr::operator<(const HasPtr &rhs)const
{
return *ps < *rhs.ps;
}
void main()
{
vector<HasPtr> vh;
int n = 10;
for (int i = 0; i < n; ++i)
vh.push_back(to_string(n - i));
for (auto p : vh)
cout << *p << " ";
cout << endl;
sort(vh.begin(), vh.end());
for (auto p : vh)
cout << *p << " ";
cout << endl;
}
习题13-32
默认版本的swap简单交换两个对象的非静态成员,已经能够满足要求了,与专业版本所实现的功能一样。
习题13-33
folder.insert()函数如果参数类型不是引用,就会将形参的指针添加进去,而非原始的Folder指针。
对于addMsg()会改变Folder内容,所以参数不能是const;
习题13-34
class Message
{
friend class Folder;
friend void swap(Message &lhs, Message &rhs);
public:
explicit Message(const string &str=""):
contents(str){}
Message(const Message &);
Message &operator=(const Message &);
~Message();
void save(Folder &);
void remove(Folder &);
private:
string contents;
set<Folder*> folders;
void add_to_Folders(const Message&);
void remove_from_Folders();
};
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);
}
void Message::remove_from_Folders()
{
for (auto f : folders)
f->remMsg(this);
}
Message::~Message()
{
remove_from_Folders();
}
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.folders, rhs.folders);
swap(lhs.contents, rhs.contents);
for (auto f : lhs.folders)
f->addMsg(&lhs);
for (auto f : rhs.folders)
f->addMsg(&rhs);
}
习题13-35
使用合成拷贝成员,可以简单的拷贝两个数据成员,但是还要将Message添加到对应的Folder中,默认的拷贝成员只对本身有用,对folder没有处理作用;
习题13-36
class Message
{
friend class Folder;
friend void swap(Message &lhs, Message &rhs);
public:
explicit Message(const string &str=""):
contents(str){}
Message(const Message &);
Message &operator=(const Message &);
~Message();
void save(Folder &);
void remove(Folder &);
void addFlr(Folder *f);
private:
string contents;
set<Folder*> folders;
void add_to_Folders(const Message&);
void remove_from_Folders();
};
void Message::save(Folder &f)
{
folders.insert(&f);
f.addMsg(this);
}
void Message::addFlr(Folder *f)
{
folders.insert(f);
}
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);
}
void Message::remove_from_Folders()
{
for (auto f : folders)
f->remMsg(this);
}
Message::~Message()
{
remove_from_Folders();
}
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.folders, rhs.folders);
swap(lhs.contents, rhs.contents);
for (auto f : lhs.folders)
f->addMsg(&lhs);
for (auto f : rhs.folders)
f->addMsg(&rhs);
}
class Folder
{
friend class Message;
friend void swap(Folder &, Folder &);
public:
void addMsg(Message *m);
void remMsg(Message *m);
Folder(const Folder &);
Folder &operator=(const Folder &f);
~Folder();
private:
set<Message*> msgs;
void add_to_Messages(const Folder &);
void remove_from_Msgs();
};
void Folder::addMsg(Message *m)
{
msgs.insert(m);
}
void Folder::remMsg(Message *m)
{
msgs.erase(m);
}
void Folder::add_to_Messages(const Folder &f)
{
for (auto m : f.msgs)
m->addFlr(this);
}
Folder::Folder(const Folder &f) :
msgs(f.msgs)
{
add_to_Messages(f);
}
void Folder::remove_from_Msgs()
{
for (auto m : msgs)
m->remove(*this);
}
Folder::~Folder()
{
remove_from_Msgs();
}
Folder &Folder::operator=(const Folder &f)
{
remove_from_Msgs();
msgs = f.msgs;
add_to_Messages(f);
return *this;
}
void swap(Folder &lhs, Folder &rhs)
{
using std::swap;
for (auto f : lhs.msgs)
f->remove(lhs);
for (auto f : rhs.msgs)
f->remove(rhs);
swap(lhs.msgs, rhs.msgs);
for (auto f : lhs.msgs)
f->addFlr(&lhs);
for (auto f : rhs.msgs)
f->addFlr(&rhs);
}
习题13-37
void Message::addFlr(Folder *f)
{
folders.insert(f);
}
void Message::remFlr(Folder *f)
{
folders.erase(f);
}
习题13-38
如果采用拷贝并交换方式,执行过程:
1.采用拷贝交换,形参不是引用类型,实参传递给形参,要使用一次Message拷贝构造函数;
2.调用swap函数时候,swap函数处理起来很复杂;
3.形参销魂时,析构函数还要调用一次;
如果用拷贝交换处理赋值问题,会增加复杂度;
习题13-39
class StrVec
{
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()const { return first_free - elements; }
size_t capacity()const { return cap - elements; }
string *begin() const { return elements; }
string *end() const { return first_free; }
void reserve(size_t n);
void reallocate(size_t n);
void resize(size_t n);
void resize(size_t n, string &s);
private:
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;
};
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(*elem++));
free();
elements = newdata;
first_free = dest;
cap = elements + newcapacity;
}
void StrVec::reallocate(size_t n)
{
auto newcapacity = n;
auto newdata = alloc.allocate(newcapacity);
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 + newcapacity;
}
void StrVec::reserve(size_t n)
{
if (n > capacity())
reallocate(n);
}
void StrVec::resize(size_t n)
{
if (n > size())
{
while (n > size())
push_back("");
}
else if (n < size())
{
while (size() > n)
alloc.destroy(--first_free);
}
}
void StrVec::resize(size_t n, const string &s)
{
if (n > size())
{
while (n > size())
push_back(s);
}
}
习题13-40
StrVec::StrVec(initializer_list<string> il)
{
auto newdata = alloc_n_copy(il.begin(), il.end());
elements = newdata.first;
first_free = cap = newdata.second;
}