13.5:
class HasPtr
{
public:
HasPtr(const string&s =string()):ps(new string(s)),i(0){}
HasPtr(const HasPtr&);
private:
string* ps;
int i;
};
HasPtr::HasPtr(const HasPtr& h) :ps(new string(*h.ps)),i(h.i){}
13.8:
class HasPtr
{
public:
HasPtr(const string&s =string()):ps(new string(s)),i(0){}
HasPtr(const HasPtr& h) : ps(new string(*h.ps)), i(h.i) {}
HasPtr& operator=(const HasPtr& h)
{
string* temp_ps = new string(*h.ps);
delete ps;
ps = temp_ps;
i = h.i;
return *this;
}
private:
string* ps;
int i;
};
13.11:
class HasPtr
{
public:
HasPtr(const string&s =string()):ps(new string(s)),i(0){}
HasPtr(const HasPtr& h) : ps(new string(*h.ps)), i(h.i) {}
HasPtr& operator=(const HasPtr& h)
{
string* temp_ps = new string(*h.ps);
delete ps;
ps = temp_ps;
i = h.i;
return *this;
}
~HasPtr()
{
delete ps;
}
private:
string* ps;
int i;
};
13.13:
#include<iostream>
using namespace std;
#include<vector>
struct X
{
X() { cout << "x()" << endl; }
X(const X&) { cout << "x(const x&)" << endl; }
};
void test01(X x1){}
void test02(X &x2){}
int main()
{
X x;
test01(x);
test02(x);
cout << endl;
X* p = new X(x);
vector<X>vex;
vex.push_back(x);
return 0;
}
13.17:
#include<iostream>
using namespace std;
class numbered
{
public:
numbered()
{
i = num++;
}
numbered(const numbered& n)
{
i = n.i + 6;
}
int i;
static int num;
};
int numbered::num = 10;
void f(const numbered& s)
{
cout << s.i << endl;
}
int main()
{
numbered a, b = a, c = b;
f(a); f(b); f(c);
return 0;
}
13.18:
#include<iostream>
using namespace std;
class Employee
{
friend void print(const Employee& e);
public:
Employee():m_id(ID++){}
Employee(const string& name):m_name(name),m_id(ID++){}
private:
string m_name;
int m_id;
static int ID;
};
int Employee::ID = 0;
void print(const Employee& e)
{
cout << "姓名: " << e.m_name << " 雇员证号: " << e.m_id << endl;
}
int main()
{
Employee e1;
print(e1);
Employee e2("张三");
print(e2);
return 0;
}
13.19:
#include<iostream>
using namespace std;
class Employee
{
friend void print(const Employee& e);
public:
Employee():m_id(ID++){}
Employee(const string& name):m_name(name),m_id(ID++){}
Employee(const Employee&) = delete;
Employee& operator=(const Employee&) = delete;
private:
string m_name;
int m_id;
static int ID;
};
int Employee::ID = 0;
void print(const Employee& e)
{
cout << "姓名: " << e.m_name << " 雇员证号: " << e.m_id << endl;
}
int main()
{
Employee e1;
print(e1);
Employee e2("张三");
print(e2);
//Employee e3(e2);报错
return 0;
}
13.22:
和11题一模一样哦
class HasPtr
{
public:
HasPtr(const string& s = string()) :ps(new string(s)), i(0) {}
HasPtr(const HasPtr& h) : ps(new string(*h.ps)), i(h.i) {}
HasPtr& operator=(const HasPtr& h)
{
string* temp_ps = new string(*h.ps);
delete ps;
ps = temp_ps;
i = h.i;
return *this;
}
~HasPtr()
{
delete ps;
}
private:
string* ps;
int i;
};
13.26:
#pragma once
#include<iostream>
using namespace std;
#include<vector>
class constStrBlobPtr;
class StrBlob
{
public:friend class constStrBlobPtr;
using size_type = vector<string>::size_type;
StrBlob() :data(make_shared<vector<string>>()) {};
StrBlob(initializer_list<string> il) :data(make_shared<vector<string>>(il)) {};
size_type size() { return data->size(); }
bool empty()const { return data->empty(); }
void push_back(const string& s) { data->push_back(s); }
void pop_back()
{
check(0, "pop_back on empty StrBlob");
data->pop_back();
}
string& front()
{
check(0, "front on empty StrBlob");
return data->front();
}
string& back()
{
check(0, "front on empty StrBlob");
return data->back();
}
const string& front()const
{
check(0, "front on empty StrBlob");
return data->front();
}
const string& back()const
{
check(0, "front on empty StrBlob");
return data->back();
}
constStrBlobPtr begin()const;
constStrBlobPtr end()const;
StrBlob(const StrBlob& sb)
{
this->data = make_shared<vector<string>>(*sb.data);
}
StrBlob& operator=(const StrBlob& sb)
{
this->data = make_shared<vector<string>>(*sb.data);
return *this;
}
private:
shared_ptr<vector<string>>data;
void check(size_type i, const string& msg)const
{
if (i >= data->size())
{
throw out_of_range(msg);
}
}
};
class constStrBlobPtr
{
public:
constStrBlobPtr() :curr(0) {}
constStrBlobPtr(const StrBlob& a, size_t sz = 0) :wptr(a.data), curr(sz) {}
const string& deref()const
{
auto p = check(curr, "dereference past end");
return (*p)[curr];
}
constStrBlobPtr& incr()
{
check(curr, "increment past end of StrBlobptr");
++curr;
return *this;
}
bool operator==(const constStrBlobPtr& a) { return this->curr == a.curr; }
bool operator!=(const constStrBlobPtr& a) { return !this->operator==(a); }
private:
weak_ptr<vector<string>>wptr;
size_t curr;
shared_ptr<vector<string>> check(size_t i, const string& msg)const
{
auto ret = wptr.lock();
if (!ret)
{
throw runtime_error("unbound StrBlobPtr");
}
if (i >= ret->size())
{
throw out_of_range(msg);
}
return ret;
}
};
constStrBlobPtr StrBlob::begin()const { return constStrBlobPtr(*this); }
constStrBlobPtr StrBlob::end()const
{
auto ret = constStrBlobPtr(*this, data->size());
return ret;
}
13.27:
#include<iostream>
using namespace std;
class HasPtr
{
public:
HasPtr(const string& s = string()) :ps(new string(s)), i(0),use(new size_t(1)) {}
HasPtr(const HasPtr& h) : ps(h.ps), i(h.i),use(h.use)
{
++* use;
}
HasPtr& operator=(const HasPtr& h)
{
++* h.use;
if (-- * use == 0)
{
delete ps;
delete use;
}
ps = h.ps;
use = h.use;
i = h.i;
return *this;
}
~HasPtr()
{
if (--*use == 0)
{
delete ps;
delete use;
}
}
private:
string* ps;
int i;
size_t* use;
};
13.28:
#include<iostream>
using namespace std;
class TreeNode
{
public:
TreeNode():value(string()),count(new int(1)),left(nullptr),right(nullptr){}
TreeNode(const TreeNode&tn):value(tn.value),count(tn.count),left(tn.left),right(tn.right)
{
++* count;
}
TreeNode& operator=(const TreeNode& tn)
{
++* tn.count;
if (-- * count == 0)
{
delete left;
delete right;
delete count;
}
value = tn.value;
count = tn.count;
left = tn.left;
right = tn.right;
return *this;
}
~TreeNode()
{
if (-- * count == 0)
{
delete left;
delete right;
delete count;
}
}
private:
string value;
int *count;
TreeNode* left;
TreeNode* right;
};
class BinStrTree
{
public:
BinStrTree():root(new TreeNode()) {}
BinStrTree(const BinStrTree&ns):root(new TreeNode(*ns.root)) {}
BinStrTree& operator=(const BinStrTree& bs)
{
TreeNode* new_root = new TreeNode(*bs.root);
delete root;
root = new_root;
return *this;
}
~BinStrTree()
{
delete root;
}
private:
TreeNode* root;
};
13.30:
#include<iostream>
using namespace std;
class HasPtr
{
friend void swap(HasPtr& h1, HasPtr& h2);
public:
HasPtr(const string& s = string()) :ps(new string(s)), i(0) {}
HasPtr(const HasPtr& h) : ps(new string(*h.ps)), i(h.i) {}
HasPtr& operator=(const HasPtr& h)
{
string* temp_ps = new string(*h.ps);
delete ps;
ps = temp_ps;
i = h.i;
return *this;
}
~HasPtr()
{
delete ps;
}
private:
string* ps;
int i;
};
void swap(HasPtr& h1, HasPtr& h2)
{
using std::swap;
swap(h1.ps, h2.ps);
swap(h1.i, h2.i);
cout << "swap" << endl;
}
13.31:
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
class HasPtr
{
friend void swap(HasPtr& h1, HasPtr& h2);
public:
HasPtr(const string& s = string()) :ps(new string(s)), i(0) {}
HasPtr(const HasPtr& h) : ps(new string(*h.ps)), i(h.i) {}
HasPtr& operator=(HasPtr h)
{
this->swap(h);
return *this;
}
bool operator<(const HasPtr& hp)
{
return *ps < *hp.ps;
}
void show() const
{
cout << *ps << endl;
}
void swap(HasPtr& h1)
{
using std::swap;
swap(ps, h1.ps);
swap(i, h1.i);
cout << "swapedf" << endl;
}
~HasPtr()
{
delete ps;
}
private:
string* ps;
int i;
};
void swap(HasPtr& h1, HasPtr& h2)
{
h1.swap(h2);
}
int main()
{
HasPtr s{ "s" }, a{ "a" }, c{ "c" };
vector<HasPtr> vec{ s, a, c };
sort(vec.begin(), vec.end());
for (auto const& elem : vec) elem.show();
}
13.34-36:
message.h:
#pragma once
#include<iostream>
using namespace std;
#include<set>
class Folder;
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 print_debug();
private:
string contents;
set<Folder*> folders;
void add_to_Folders(const Message&);
void remove_from_Folders();
void addFldr(Folder* f) { folders.insert(f); }
void remFldr(Folder* f) { folders.erase(f); }
};
void swap(Message& lhs, Message& rhs);
class Folder
{
friend class Message;
friend void swap(Folder&, Folder&);
public:
Folder() = default;
Folder(const Folder&);
Folder& operator=(const Folder&);
~Folder();
void print_debug();
private:
set<Message*> msgs;
void add_to_Message(const Folder&);
void remove_from_Message();
void addMsg(Message* m)
{
msgs.insert(m);
}
void remMsg(Message* m)
{
msgs.erase(m);
}
};
void swap(Folder&, Folder&);
message.cpp:
#include"message.h"
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);
}
}
void Message::print_debug()
{
cout << contents << endl;
}
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;
lhs.remove_from_Folders();
rhs.remove_from_Folders();
swap(lhs.contents, rhs.contents);
swap(lhs.folders, rhs.folders);
lhs.add_to_Folders(lhs);
rhs.add_to_Folders(rhs);
}
void swap(Folder&lhs, Folder&rhs)
{
using std::swap;
lhs.remove_from_Message();
rhs.remove_from_Message();
swap(lhs.msgs, rhs.msgs);
lhs.add_to_Message(lhs);
rhs.add_to_Message(rhs);
}
void Folder::add_to_Message(const Folder&f)
{
for (auto m : f.msgs)
{
m->addFldr(this);
}
}
Folder::Folder(const Folder&f):msgs(f.msgs)
{
add_to_Message(f);
}
void Folder::remove_from_Message()
{
for (auto m : msgs)
{
m->remFldr(this);
}
}
Folder& Folder::operator=(const Folder&f)
{
remove_from_Message();
this->msgs = f.msgs;
add_to_Message(f);
return(*this);
}
Folder::~Folder()
{
remove_from_Message();
}
void Folder::print_debug()
{
for (auto m : msgs)
{
cout << m->contents << " ";
}cout << endl;
}
13.39:
StrVec.h:
#pragma once
#include<iostream>
using namespace std;
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(const size_t&);
void resize(size_t count,const string&s);
void resize(size_t count);
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;//指向数组尾后;
};
StrVec.cpp:
#include"strvec.h"
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;
cap = first_free = newdata.second;
}
StrVec::~StrVec()
{
free();
}
StrVec& StrVec::operator=(const StrVec&s)
{
auto data = alloc_n_copy(s.begin(), s.end());
free();
elements = data.first;
cap = first_free = data.second;
return *this;
}
void StrVec::reallocate()
{
auto newcapacity = size() ? size() * 2 : 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::reserve(const size_t&i)
{
if (i <= capacity()) { return; }
auto newcapacity = i;
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::resize(size_t count, const string& s)
{
if (count > size())
{
if (count > capacity())
{
reserve(count * 2);
}
for (size_t i = size(); i != count; ++i)
{
alloc.construct(first_free++, s);
}
}
else if (count < size())
{
while (first_free != elements + count)
{
alloc.destroy(--first_free);
}
}
}
void StrVec::resize(size_t count)
{
resize(count, string());
}
13.40:
StrVec.h:
#pragma once
#include<iostream>
using namespace std;
class StrVec
{
public:
StrVec():elements(nullptr),first_free(nullptr),cap(nullptr){}
StrVec(const StrVec&);
StrVec(const initializer_list<string>&);
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(const size_t&);
void resize(size_t count,const string&s);
void resize(size_t count);
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;//指向数组尾后;
};
StrVec.cpp:
#include"strvec.h"
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;
cap = first_free = newdata.second;
}
StrVec::~StrVec()
{
free();
}
StrVec& StrVec::operator=(const StrVec&s)
{
auto data = alloc_n_copy(s.begin(), s.end());
free();
elements = data.first;
cap = first_free = data.second;
return *this;
}
void StrVec::reallocate()
{
auto newcapacity = size() ? size() * 2 : 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::reserve(const size_t&i)
{
if (i <= capacity()) { return; }
auto newcapacity = i;
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::resize(size_t count, const string& s)
{
if (count > size())
{
if (count > capacity())
{
reserve(count * 2);
}
for (size_t i = size(); i != count; ++i)
{
alloc.construct(first_free++, s);
}
}
else if (count < size())
{
while (first_free != elements + count)
{
alloc.destroy(--first_free);
}
}
}
void StrVec::resize(size_t count)
{
resize(count, string());
}
StrVec::StrVec(const initializer_list<string>&is)
{
auto newdata = alloc_n_copy(is.begin(), is.end());
elements = newdata.first;
cap = first_free = newdata.second;
}
13.42:
2022年3月23日晚11点15分,真不想做这道题了,太恶心了。
13.43:
#include"strvec.h"
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_each(elements, first_free, [this](string& rhs) {alloc.destroy(&rhs); });
alloc.deallocate(elements,cap - elements);
}
}
StrVec::StrVec(const StrVec& s)
{
auto newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
cap = first_free = newdata.second;
}
StrVec::~StrVec()
{
free();
}
StrVec& StrVec::operator=(const StrVec&s)
{
auto data = alloc_n_copy(s.begin(), s.end());
free();
elements = data.first;
cap = first_free = data.second;
return *this;
}
void StrVec::reallocate()
{
auto newcapacity = size() ? size() * 2 : 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::reserve(const size_t&i)
{
if (i <= capacity()) { return; }
auto newcapacity = i;
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::resize(size_t count, const string& s)
{
if (count > size())
{
if (count > capacity())
{
reserve(count * 2);
}
for (size_t i = size(); i != count; ++i)
{
alloc.construct(first_free++, s);
}
}
else if (count < size())
{
while (first_free != elements + count)
{
alloc.destroy(--first_free);
}
}
}
void StrVec::resize(size_t count)
{
resize(count, string());
}
StrVec::StrVec(const initializer_list<string>&is)
{
auto newdata = alloc_n_copy(is.begin(), is.end());
elements = newdata.first;
cap = first_free = newdata.second;
}
13.44:
string.h:
#pragma once
#include<iostream>
using namespace std;
#include<algorithm>
class String
{
public:
String():String("") {}
String(const String&);
String(const char*);
String& operator=(const String&);
~String();
const char* c_str() const { return elements; }
size_t size() const { return end - elements; }
size_t length() const { return end - elements - 1; }
private:
pair<char*, char*>alloc_n_copy(const char*, const char*);
void range_initializer(const char*, const char*);
void free();
char* elements;
char* end;
allocator<char>alloc;
};
string.cpp
#include"string.h"
pair<char*, char*>String::alloc_n_copy(const char*b, const char*e)
{
auto str = alloc.allocate(e - b);
return { str,uninitialized_copy(b,e,str) };
}
void String::range_initializer(const char*b, const char*e)
{
auto newstr = alloc_n_copy(b, e);
elements = newstr.first;
end = newstr.second;
}
String::String(const char*s)
{
char* s1 = const_cast<char*>(s);
while (*s1)
{
++s1;
}
range_initializer(s, ++s1);
}
String::String(const String&rhs)
{
range_initializer(rhs.elements, rhs.end);
cout << "copy constructor" << endl;
}
void String::free()
{
if (elements)
{
for_each(elements, end, [this](char& c) {alloc.destroy(&c); });
alloc.deallocate(elements, end - elements);
}
}
String::~String()
{
free();
}
String& String::operator=(const String&rhs)
{
auto newstr = alloc_n_copy(rhs.elements, rhs.end);
free();
elements = newstr.first;
end = newstr.second;
cout << "copy assignment" << endl;
return *this;
}
text:
#include "string.h"
#include <vector>
#include <iostream>
void foo(String x)
{
std::cout << x.c_str() << std::endl;
}
void bar(const String& x)
{
std::cout << x.c_str() << std::endl;
}
String baz()
{
String ret("world");
return ret;
}
int main()
{
char text[] = "world";
String s0;
String s1("hello");
String s2(s0);
String s3 = s1;
String s4(text);
s2 = s1;
foo(s1);
bar(s1);
foo("temporary");
bar("temporary");
String s5 = baz();
std::vector<String> svec;
svec.reserve(8);
svec.push_back(s0);
svec.push_back(s1);
svec.push_back(s2);
svec.push_back(s3);
svec.push_back(s4);
svec.push_back(s5);
svec.push_back(baz());
svec.push_back("good job");
for (const auto& s : svec) {
std::cout << s.c_str() << std::endl;
}
}
13.49:
strvec.h:
#pragma once
#include<iostream>
using namespace std;
#include<algorithm>
class StrVec
{
public:
StrVec():elements(nullptr),first_free(nullptr),cap(nullptr){}
StrVec(const StrVec&);
StrVec(const initializer_list<string>&);
StrVec& operator=(const StrVec&);
StrVec(StrVec&&) noexcept;
StrVec& operator=(StrVec&&) noexcept;
~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(const size_t&);
void resize(size_t count,const string&s);
void resize(size_t count);
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;//指向数组尾后;
};
strvec.cpp:
#include"strvec.h"
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_each(elements, first_free, [this](string& rhs) {alloc.destroy(&rhs); });
alloc.deallocate(elements,cap - elements);
}
}
StrVec::StrVec(const StrVec& s)
{
auto newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
cap = first_free = newdata.second;
}
StrVec::~StrVec()
{
free();
}
StrVec& StrVec::operator=(const StrVec&s)
{
auto data = alloc_n_copy(s.begin(), s.end());
free();
elements = data.first;
cap = first_free = data.second;
return *this;
}
void StrVec::reallocate()
{
auto newcapacity = size() ? size() * 2 : 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::reserve(const size_t&i)
{
if (i <= capacity()) { return; }
auto newcapacity = i;
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::resize(size_t count, const string& s)
{
if (count > size())
{
if (count > capacity())
{
reserve(count * 2);
}
for (size_t i = size(); i != count; ++i)
{
alloc.construct(first_free++, s);
}
}
else if (count < size())
{
while (first_free != elements + count)
{
alloc.destroy(--first_free);
}
}
}
void StrVec::resize(size_t count)
{
resize(count, string());
}
StrVec::StrVec(const initializer_list<string>&is)
{
auto newdata = alloc_n_copy(is.begin(), is.end());
elements = newdata.first;
cap = first_free = newdata.second;
}
StrVec::StrVec(StrVec&& s) noexcept :elements(s.elements), first_free(s.first_free), cap(s.cap)
{
s.elements = s.cap = s.first_free = nullptr;
}
StrVec& StrVec::operator=(StrVec&& s) noexcept
{
if (this != &s)
{
free();
elements = s.elements;
first_free = s.first_free;
cap = s.cap;
s.elements = s.cap = s.first_free = nullptr;
}
return *this;
}
string.h:
#pragma once
#include<iostream>
using namespace std;
#include<algorithm>
class String
{
public:
String():String("") {}
String(const String&);
String(const char*);
String& operator=(const String&);
String(String&&)noexcept;
String& operator=(String&&)noexcept;
~String();
const char* c_str() const { return elements; }
size_t size() const { return end - elements; }
size_t length() const { return end - elements - 1; }
private:
pair<char*, char*>alloc_n_copy(const char*, const char*);
void range_initializer(const char*, const char*);
void free();
char* elements;
char* end;
allocator<char>alloc;
};
string.cpp:
#include"string.h"
pair<char*, char*>String::alloc_n_copy(const char*b, const char*e)
{
auto str = alloc.allocate(e - b);
return { str,uninitialized_copy(b,e,str) };
}
void String::range_initializer(const char*b, const char*e)
{
auto newstr = alloc_n_copy(b, e);
elements = newstr.first;
end = newstr.second;
}
String::String(const char*s)
{
char* s1 = const_cast<char*>(s);
while (*s1)
{
++s1;
}
range_initializer(s, ++s1);
}
String::String(const String&rhs)
{
range_initializer(rhs.elements, rhs.end);
cout << "copy constructor" << endl;
}
void String::free()
{
if (elements)
{
for_each(elements, end, [this](char& c) {alloc.destroy(&c); });
alloc.deallocate(elements, end - elements);
}
}
String::~String()
{
free();
}
String& String::operator=(const String&rhs)
{
auto newstr = alloc_n_copy(rhs.elements, rhs.end);
free();
elements = newstr.first;
end = newstr.second;
cout << "copy assignment" << endl;
return *this;
}
String::String(String&&s)noexcept:elements(s.elements),end(s.end)
{
s.elements = s.end = nullptr;
}
String& String::operator=(String&&s)noexcept
{
if (this != &s)
{
free();
elements = s.elements;
end = s.end;
s.elements = s.end = nullptr;
}
return *this;
}
message.h:
#pragma once
#include<iostream>
using namespace std;
#include<set>
class Folder;
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(Message&&);
Message& operator=(Message&&);
~Message();
void save(Folder&);
void remove(Folder&);
void print_debug();
void move_Folders(Message* m);
private:
string contents;
set<Folder*> folders;
void add_to_Folders(const Message&);
void remove_from_Folders();
void addFldr(Folder* f) { folders.insert(f); }
void remFldr(Folder* f) { folders.erase(f); }
};
void swap(Message& lhs, Message& rhs);
class Folder
{
friend class Message;
friend void swap(Folder&, Folder&);
public:
Folder() = default;
Folder(const Folder&);
Folder& operator=(const Folder&);
Folder(Folder&&);
Folder& operator=(Folder&&);
~Folder();
void print_debug();
void move_Message(Folder*);
private:
set<Message*> msgs;
void add_to_Message(const Folder&);
void remove_from_Message();
void addMsg(Message* m)
{
msgs.insert(m);
}
void remMsg(Message* m)
{
msgs.erase(m);
}
};
void swap(Folder&, Folder&);
message.cpp:
#include"message.h"
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);
}
}
void Message::print_debug()
{
cout << contents << endl;
}
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;
lhs.remove_from_Folders();
rhs.remove_from_Folders();
swap(lhs.contents, rhs.contents);
swap(lhs.folders, rhs.folders);
lhs.add_to_Folders(lhs);
rhs.add_to_Folders(rhs);
}
void swap(Folder&lhs, Folder&rhs)
{
using std::swap;
lhs.remove_from_Message();
rhs.remove_from_Message();
swap(lhs.msgs, rhs.msgs);
lhs.add_to_Message(lhs);
rhs.add_to_Message(rhs);
}
void Folder::add_to_Message(const Folder&f)
{
for (auto m : f.msgs)
{
m->addFldr(this);
}
}
Folder::Folder(const Folder&f):msgs(f.msgs)
{
add_to_Message(f);
}
void Folder::remove_from_Message()
{
for (auto m : msgs)
{
m->remFldr(this);
}
}
Folder& Folder::operator=(const Folder&f)
{
remove_from_Message();
this->msgs = f.msgs;
add_to_Message(f);
return(*this);
}
Folder::~Folder()
{
remove_from_Message();
}
void Folder::print_debug()
{
for (auto m : msgs)
{
cout << m->contents << " ";
}cout << endl;
}
void Message::move_Folders(Message* m)
{
folders = std::move(m->folders);
for (auto f : folders)
{
f->remMsg(m);
f->addMsg(this);
}
m->folders.clear();
}
Message::Message(Message&&m):contents(std::move(m.contents))
{
move_Folders(&m);
}
Message& Message::operator=(Message&&m)
{
if (this != &m)
{
remove_from_Folders();
contents = std::move(m.contents);
move_Folders(&m);
}
return *this;
}
void Folder::move_Message(Folder*f)
{
msgs = std::move(f->msgs);
for (auto m : msgs)
{
m->remFldr(f);
m->addFldr(this);
}
f->msgs.clear();
}
Folder::Folder(Folder&&f):msgs(std::move(f.msgs))
{
move_Message(&f);
}
Folder& Folder::operator=(Folder&&f)
{
if (this != &f)
{
remove_from_Message();
msgs = std::move(f.msgs);
move_Message(&f);
}
cout << "Message members moved" << endl;
return *this;
}
13.58:
#include <vector>
#include <iostream>
#include <algorithm>
using std::vector; using std::sort;
class Foo {
public:
Foo sorted()&&;
Foo sorted() const&;
private:
vector<int> data;
};
Foo Foo::sorted()&& {
sort(data.begin(), data.end());
std::cout << "&&" << std::endl; // debug
return *this;
}
Foo Foo::sorted() const& {
// Foo ret(*this);
// sort(ret.data.begin(), ret.data.end());
// return ret;
std::cout << "const &" << std::endl; // debug
// Foo ret(*this);
// ret.sorted(); // Exercise 13.56
// return ret;
return Foo(*this).sorted(); // Exercise 13.57
}
int main()
{
Foo().sorted(); // call "&&"
Foo f;
f.sorted(); // call "const &"
}