C++ primer习题记录——第十三章

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 &"
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值