C++ Primer: Chapter 13 Copy Control

HasPtr类

行为像值的类

class HasPtr
{
public:
	HasPtr(const string& s = string()) : ps(new string(s)), i(0) {};
	HasPtr(const HasPtr& hp) : ps(new string(*hp.ps)), i(hp.i) {};
	//重载赋值运算符
	HasPtr& operator=(const HasPtr& hp);
private:
	string* ps;
	int i;
};
HasPtr& HasPtr::operator=(const HasPtr& hp)
{
	string* temp_ps = new string(*hp.ps);
	delete ps; //销毁对象原本的ps
	ps = temp_ps; //指向hp的新空间
	i = hp.i;
	return *this;
}

行为像指针的类

class HasPtr
{
public:
	HasPtr(const string& s = string()) : ps(new string(s)), i(0), use(new size_t(1)) {};
	HasPtr(const HasPtr& hp) : ps(new string(*hp.ps)), i(hp.i), use(hp.use) { ++*use; };

	HasPtr& operator=(const HasPtr& hp);
	~HasPtr() { delete ps; };
private:
	string* ps;
	int i;
	size_t* use;
};
HasPtr& HasPtr::operator=(const HasPtr& rhs)
{
	++*rhs.use;
	if (--*use == 0)
	{
		delete use;
		delete ps;
	}
	ps = rhs.ps;
	i = rhs.i;
	use = rhs.use;
	
	return *this; 
}

TreeNode/BinStrTree类

//定义行为像值的类TreeNode
class TreeNode
{
public:
    TreeNode() {};
    TreeNode(const TreeNode& rhs) : value(rhs.value), count(rhs.count), 
                                    left(new TreeNode(*rhs.left)), right(new TreeNode(*rhs.right)) {};

    TreeNode& operator=(const TreeNode&);
    ~TreeNode() { delete left; delete right; };
private:
    string value;
    int count;
    TreeNode* left;
    TreeNode* right;
};

TreeNode& TreeNode::operator=(const TreeNode& rhs)
{
    //copy value
    value = rhs.value;
    count = rhs.count;

    //copy pointer
    auto temp_left = *rhs.left;
    auto temp_right = *rhs.right;
    delete left;
    delete right;
    left = new TreeNode(temp_left);
    right = new TreeNode(temp_right);

    return *this;

}
//定义行为像指针的类TreeNode
class BinStrTree
{
public:
    BinStrTree() : used(new size_t(1)) {};
    BinStrTree(const BinStrTree& rhs) : root(rhs.root), used(rhs.used) { ++*rhs.used; };
    BinStrTree& operator=(const BinStrTree& rhs);

private:
    TreeNode* root;
    size_t* used;
};

BinStrTree& BinStrTree::operator=(const BinStrTree& rhs)
{
    ++*rhs.used;
    if (--*used == 0)
    {
        delete root;
        delete used;
    }
    root = rhs.root;
    used = rhs.used;
    return *this;
}

Message/Floder类

对应于13.4节的内容及习题

Message.h

#pragma once
#include<set>
#include<string>

using namespace std;

class Floder;

class Message
{
	friend class Floder;
	friend void swap(Message&, Message&);
public:
	// construct func
	explicit Message(const string& str = "") : contents(str) {};
	// copy control members
	Message(const Message&);
	Message(Message&& m) : contents(std::move(m.contents)) { move_Floders(&m); };
	Message& operator=(const Message&);
	Message& operator=(Message&&);
	~Message();
	// member func
	void save(Floder&);
	void remove(Floder&);
	void addFld(Floder*);
	void remFld(Floder*);
private:
	string contents;
	set<Floder*> floders;
	void add_to_floders(const Message&);
	void remove_from_floders();
	void move_Floders(Message* m);
};

class Floder
{
	friend class Message;
public:
	Floder() {};

	void addMsg(Message *);
	void remMsg(Message *);
private:
	set<Message*> messages;
};

Message.cpp

#include"Message.h"

// ===== Message =====
void Message::save(Floder& _f)
{
	floders.insert(&_f);
	_f.addMsg(this);
}

void Message::remove(Floder& _f)
{
	floders.erase(&_f);
	_f.remMsg(this);
}

void Message::add_to_floders(const Message& _m)
{
	//让每个包含m的floder添加this
	for (auto f : _m.floders)
		f->addMsg(this);
}

Message::Message(const Message& _m) : contents(_m.contents), floders(_m.floders)
{
	add_to_floders(_m);
}


void Message::remove_from_floders()
{
	for (auto f : floders)
		f->remMsg(this);
}

Message::~Message()
{
	remove_from_floders();
}

Message& Message::operator=(const Message& rhs)
{
	remove_from_floders();
	contents = rhs.contents;
	floders = rhs.floders;
	add_to_floders(rhs);
	return *this;
}

Message& Message::operator=(Message&& rhs)
{
	if (this != &rhs)
	{
		remove_from_floders();
		contents = std::move(rhs.contents);
		move_Floders(&rhs);
	}
	return *this;
}

void swap(Message& lhs, Message& rhs)
{
	using std::swap;
	for (auto f : lhs.floders)
		f->remMsg(&lhs);
	for (auto f : rhs.floders)
		f->remMsg(&rhs);
	swap(lhs.floders, rhs.floders);
	swap(lhs.contents, rhs.contents);
	for (auto f : lhs.floders)
		f->addMsg(&lhs);
	for (auto f : rhs.floders)
		f->addMsg(&rhs);
}

void Message::addFld(Floder* _f)
{
	floders.insert(_f);
}
void Message::remFld(Floder* _f)
{
	floders.erase(_f);
}
void Message::move_Floders(Message* m)
{
	floders = std::move(m->floders);
	//在floders中删除m,并添加this
	for (auto f : floders)
	{
		f->remMsg(m);
		f->addMsg(this);
	}
	m->floders.clear();
}

// ===== Floder =====
void Floder::addMsg(Message* _m)
{
	messages.insert(_m);
}

void Floder::remMsg(Message* _m)
{
	messages.erase(_m);
}

StrVec类

StrVec.h

#pragma once
#include<string>
#include<memory>
#include<utility>

using namespace std;

class StrVec
{
public:
	// construct func
	StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) {};
	StrVec(const initializer_list<string>&);
	// copy control member
	StrVec(const StrVec&);
	StrVec(StrVec&&) noexcept;
	StrVec& operator=(const StrVec&);
	StrVec& operator=(StrVec&&) noexcept;
	~StrVec() {};
	// member func
	void push_back(const string&);
	void push_back(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(const size_t&, const string&);

	string& getvalue(size_t index) { return *(elements + index); };

private:
	allocator<string> alloc; //为string元素分配内存
	void chk_n_alloc() { if (size() == capacity()) reallocate(); }; //如果大小等于容量,则重新分配空间
	pair<string*, string*> alloc_n_copy(const string*, const string*);
	void free(); //销毁元素并释放内存
	void reallocate(); //重新分配内存空间
	string* elements; // pointer to first element
	string* first_free; // pointer to the next pos of last element
	string* cap; // pointer to the next pos of alloc
};

StrVec.cpp

#include"StrVec.h"
#include<algorithm>

StrVec::StrVec(const initializer_list<string>& sl)
{
	for (auto& s : sl)
		push_back(s);
}

void StrVec::push_back(const string& s)
{
	chk_n_alloc();
	alloc.construct(first_free++, s); //在first_free处添加元素s,并移动指针
}

void StrVec::push_back(string&& s)
{
	chk_n_alloc();
	alloc.construct(first_free++, std::move(s)); //在first_free处添加元素s的右值,并移动指针
}

pair<string*, string*> StrVec::alloc_n_copy(const string* b, const string* e)
{
	//分配新空间
	auto data = alloc.allocate(e - b);
	//初始化并返回一个pair
	return make_pair(data, uninitialized_copy(b, e, data));
}

void StrVec::free()
{
	if (elements)
	{
		for_each(elements, first_free, [this](string& s) {alloc.destroy(&s); });
		//销毁所有元素
		//for (auto p = first_free; p != elements; )
		//	alloc.destroy(--p);
		//释放内存
		alloc.deallocate(elements, cap - elements);
	}
}

StrVec::StrVec(const StrVec& s)
{
	//调用alloc_n_copy分配空间以容纳与s中一样多的元素
	auto newdata = alloc_n_copy(s.begin(), s.end());
	elements = newdata.first;
	first_free = cap = newdata.second;
}

StrVec::StrVec(StrVec&& s) noexcept
{
	auto newdata = alloc_n_copy(s.begin(), s.end());
	elements = newdata.first;
	first_free = cap = newdata.second;
	s.elements = s.first_free = s.cap = nullptr;
}

StrVec& StrVec::operator=(const StrVec& rhs)
{
	//调用alloc_n_copy分配空间以容纳与rhs中一样多的元素
	auto data = alloc_n_copy(rhs.begin(), rhs.end());
	free();
	elements = data.first;
	first_free = cap = data.second;
	return *this;
}

StrVec& StrVec::operator=(StrVec&& rhs) noexcept
{
	if (this != &rhs)
	{
		//调用alloc_n_copy分配空间以容纳与rhs中一样多的元素
		auto data = alloc_n_copy(rhs.begin(), rhs.end());
		free();
		elements = data.first;
		first_free = cap = data.second;
		rhs.elements = rhs.first_free = rhs.cap = nullptr;
	}
	
	return *this;
}

void StrVec::reallocate()
{
	// newcapacity表示当前内存空间的两倍大小
	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++, move(*elem++));
	free(); //完成移动后释放旧内存空间
	elements = newdata;
	first_free = dest;
	cap = elements + newcapacity;
}

void StrVec::reserve(const size_t& n)
{
	// 分配新内存
	auto newdata = alloc.allocate(n);
	// 将数据从旧内存移动到新内存
	auto dest = newdata;
	auto elem = elements;
	for (size_t i = 0; i != size(); ++i)
		alloc.construct(dest++, move(*elem++));
	free(); //完成移动后释放旧内存空间
	elements = newdata;
	first_free = dest;
	cap = elements + n;
}

void StrVec::resize(const size_t& n, const string& s = string())
{
	if (n < size())
	{
		for (auto it = elements + n; it != first_free; it++)
			alloc.destroy(it);
		alloc.deallocate(elements + n, size()-n);
	}
	else
	{
		for(int i = 0; i< n - size(); ++i)
			push_back(s);
	}
}

Homework

Test 13.5

#include<string>

using std::string;

class HasPtr
{
public:
	HasPtr(const string& s = string()) : ps(new string(s)), i(0) {};
	HasPtr(const HasPtr& hp) : ps(new string(*hp.ps)), i(hp.i) {};
private:
	string* ps;
	int i;
};

Test 13.8

class HasPtr
{
public:
	HasPtr(const string& s = string()) : ps(new string(s)), i(0) {};
	HasPtr(const HasPtr& hp) : ps(new string(*hp.ps)), i(hp.i) {};
	//重载赋值运算符
	HasPtr& operator=(const HasPtr& hp);
private:
	string* ps;
	int i;
};

HasPtr& HasPtr::operator=(const HasPtr& hp)
{
	string* temp_ps = new string(*hp.ps);
	delete ps; //销毁对象原本的ps
	ps = temp_ps; //指向hp的新空间
	i = hp.i;
	return *this;
}

Test 13.13

struct X 
{
    X() { cout << "X()" << endl; }
    X(const X&) { cout << "X(const X&)" << endl; }

    X& operator=(const X&) { cout << "X& operator=(const X&)" << endl; };
    ~X() { cout << "~X()" << endl; };
};

void func(X& x1, X x2)
{
    cout << "func end" << endl;
}
int main()
{
    X x0;

    cout << "==========================" << endl;

    func(x0, X());

    cout << "==========================" << endl;

    auto xp = new X();

    cout << "==========================" << endl;

    vector<X> xvec{ X() };
    
    

    return 0;
}

Test 13.14

static int seq = 0;

class numbered
{
public:
    numbered() : mysn(seq++){ };
    int mysn;

    //numbered& operator=(numbered&);
};

void f(numbered s)
{
    cout << s.mysn << endl;
}

int main()
{
    numbered a, b = a, c = b;
    f(a);
    f(b);
    f(c);

    return 0;
}

最后输出的三个结果相同,都是0

Test 13.15

static int seq = 0;

class numbered
{
public:
    numbered() : mysn(seq++){ };
    numbered(const numbered &) : mysn(seq++) { };
    int mysn;
    
};


void f(numbered s)
{
    cout << s.mysn << endl;
}

int main()
{
    numbered a, b = a, c = b;
    f(a);
    f(b);
    f(c);

    return 0;
}

输出的结果为3 4 5

Test 13.16

static int seq = 0;

class numbered
{
public:
    numbered() : mysn(seq++){ };
    numbered(const numbered &) : mysn(seq++) { };
    int mysn;
    
};


void f(numbered& s)
{
    cout << s.mysn << endl;
}

int main()
{
    numbered a, b = a, c = b;
    f(a);
    f(b);
    f(c);

    return 0;
}

输出的结果为0 1 2

Test 13.17

见Test 13.13-13.17

Test 13.18

struct Employee
{
public:
    Employee() {};
    Employee(const string& s) : name(s), id(++seq) {};
    string name;
    int id;
private:
    static int seq;
};

int Employee::seq = 0;

Test 13.19

struct Employee
{
public:
    Employee() {};
    Employee(const string& s) : name(s), id(++seq) {};
    Employee(const Employee& e) : name(e.name), id(++seq) { };
    string name;
    int id;
    Employee& operator=(const Employee& e) { name = e.name; return *this; };
private:
    static int seq;
};

int Employee::seq = 0;

int main()
{
    Employee e1("hj");
    Employee e2 = e1;


    cout << e2.id << e1.id;

    return 0;
}

Test 13.22

class HasPtr
{
public:
	HasPtr(const string& s = string()) : ps(new string(s)), i(0) {};
	HasPtr(const HasPtr& hp) : ps(new string(*hp.ps)), i(hp.i) {};

	HasPtr& operator=(const HasPtr& hp);
	~HasPtr() {};
private:
	string* ps;
	int i;
};

Test 13.23


Test 13.26

class strblob
{
	friend class strblobptr;
	friend class conststrblobptr;
public:

	typedef vector<string>::size_type size_type;
	strblob() : data(make_shared<vector<string>>()) {};
	strblob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {}; //可传入任意大小的string链表
	strblob(const strblob& sb) : data(make_shared<vector<string>>(*sb.data)) {};
	
	size_type size() const { return data->size(); } //函数体调用的size()是vector的size()成员函数
	bool empty() const { return data->empty(); }
	//添加和删除元素
	void push_back(const string& t) { data->push_back(t); };
	void pop_back();
	//元素访问
	string& front();
	const string& front() const;
	string& back();
	const string& back() const;
	//迭代器操作
	strblobptr begin();
	strblobptr end();
	//拷贝控制
	strblob& operator=(const strblob& sb);

private:
	//strblob类的底层是一个vector<string>
	shared_ptr<vector<string>> data;
	//如果data[i]不合法,抛出一个异常
	void check(size_type i, const string& msg) const;
};
//拷贝控制
strblob& strblob::operator=(const strblob& rhs)
{
	data = make_shared<vector<string>>(*rhs.data);
	return *this;
}

Test 13.27

class HasPtr
{
public:
	HasPtr(const string& s = string()) : ps(new string(s)), i(0), use(new size_t(1)) {};
	HasPtr(const HasPtr& hp) : ps(new string(*hp.ps)), i(hp.i), use(hp.use) { ++*use; };

	HasPtr& operator=(const HasPtr& hp);
	~HasPtr() { delete ps; };
private:
	string* ps;
	int i;
	size_t* use;
};
HasPtr& HasPtr::operator=(const HasPtr& rhs)
{
	++*rhs.use;
	if (--*use == 0)
	{
		delete use;
		delete ps;
	}
	ps = rhs.ps;
	i = rhs.i;
	use = rhs.use;
	
	return *this; 
}

Test 13.28

//定义行为像值的类TreeNode
class TreeNode
{
public:
    TreeNode() {};
    TreeNode(const TreeNode& rhs) : value(rhs.value), count(rhs.count), 
                                    left(new TreeNode(*rhs.left)), right(new TreeNode(*rhs.right)) {};

    TreeNode& operator=(const TreeNode&);
    ~TreeNode() { delete left; delete right; };
private:
    string value;
    int count;
    TreeNode* left;
    TreeNode* right;
};

TreeNode& TreeNode::operator=(const TreeNode& rhs)
{
    //copy value
    value = rhs.value;
    count = rhs.count;

    //copy pointer
    auto temp_left = *rhs.left;
    auto temp_right = *rhs.right;
    delete left;
    delete right;
    left = new TreeNode(temp_left);
    right = new TreeNode(temp_right);

    return *this;

}
//定义行为像指针的类TreeNode
class BinStrTree
{
public:
    BinStrTree() : used(new size_t(1)) {};
    BinStrTree(const BinStrTree& rhs) : root(rhs.root), used(rhs.used) { ++*rhs.used; };
    BinStrTree& operator=(const BinStrTree& rhs);

private:
    TreeNode* root;
    size_t* used;
};

BinStrTree& BinStrTree::operator=(const BinStrTree& rhs)
{
    ++*rhs.used;
    if (--*used == 0)
    {
        delete root;
        delete used;
    }
    root = rhs.root;
    used = rhs.used;
    return *this;
}

Test 13.30 & 13.31

HasPtr.h

class HasPtr
{
	friend void swap(HasPtr&, HasPtr&);
public:
	HasPtr(const string& s = string()) : ps(new string(s)), i(0) {};
	HasPtr(const HasPtr& hp) : ps(new string(*hp.ps)), i(hp.i) {};
	
	HasPtr& operator=(const HasPtr&);
	bool operator<(const HasPtr&) const;

	string getstr() const;

private:
	string* ps;
	int i;
};

inline
void swap(HasPtr& lhs, HasPtr& rhs)
{
	using std::swap;
	std::cout << "do swap" << std::endl;
	swap(lhs.ps, rhs.ps);
	swap(lhs.i, rhs.i);
}

HasPtr.cpp

HasPtr& HasPtr::operator=(const HasPtr& hp)
{
	string* temp_ps = new string(*hp.ps);
	delete ps; 
	ps = temp_ps; 
	i = hp.i;
	return *this;
}

bool HasPtr::operator<(const HasPtr& rhs) const
{
	return *ps < *rhs.ps;
}

string HasPtr::getstr() const
{
	return *(this->ps);
}

main.cpp

int main()
{
    vector<HasPtr> hv{ HasPtr("bbb"), HasPtr("eee"),HasPtr("ccc"), HasPtr("aaa") };
    for (auto& h : hv)
        cout << h.getstr() << " ";
    cout << endl;

    sort(hv.begin(), hv.end());

    for (auto& h : hv)
        cout << h.getstr() << " ";

    return 0;
}

Test 13. 42

StrVec.h

#include<string>
#include<memory>
#include<utility>

using namespace std;

class StrVec
{
public:
	// construct func
	StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) {};
	StrVec(const initializer_list<string>&);
	// copy control member
	StrVec(const StrVec&);
	StrVec& operator=(const StrVec&);
	~StrVec() {};
	// member func
	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(const size_t&, const string&);

	string& getvalue(size_t index) { return *(elements + index); };

private:
	allocator<string> alloc; //为string元素分配内存
	void chk_n_alloc() { if (size() == capacity()) reallocate(); }; //如果大小等于容量,则重新分配空间
	pair<string*, string*> alloc_n_copy(const string*, const string*);
	void free(); //销毁元素并释放内存
	void reallocate(); //重新分配内存空间
	string* elements; // pointer to first element
	string* first_free; // pointer to the next pos of last element
	string* cap; // pointer to the next pos of alloc
};

StrVec.cpp

#include"StrVec.h"
#include<algorithm>

StrVec::StrVec(const initializer_list<string>& sl)
{
	for (auto& s : sl)
		push_back(s);
}

void StrVec::push_back(const string& s)
{
	chk_n_alloc();
	alloc.construct(first_free++, s); //在first_free处添加元素s,并移动指针
}

pair<string*, string*> StrVec::alloc_n_copy(const string* b, const string* e)
{
	//分配新空间
	auto data = alloc.allocate(e - b);
	//初始化并返回一个pair
	return make_pair(data, uninitialized_copy(b, e, data));
}

void StrVec::free()
{
	if (elements)
	{
		for_each(elements, first_free, [this](string& s) {alloc.destroy(&s); });
		//销毁所有元素
		//for (auto p = first_free; p != elements; )
		//	alloc.destroy(--p);
		//释放内存
		alloc.deallocate(elements, cap - elements);
	}
}

StrVec::StrVec(const StrVec& s)
{
	//调用alloc_n_copy分配空间以容纳与s中一样多的元素
	auto newdata = alloc_n_copy(s.begin(), s.end());
	elements = newdata.first;
	first_free = cap = newdata.second;
}

StrVec& StrVec::operator=(const StrVec& rhs)
{
	//调用alloc_n_copy分配空间以容纳与rhs中一样多的元素
	auto data = alloc_n_copy(rhs.begin(), rhs.end());
	free();
	elements = data.first;
	first_free = cap = data.second;
	return *this;
}

void StrVec::reallocate()
{
	// newcapacity表示当前内存空间的两倍大小
	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++, move(*elem++));
	free(); //完成移动后释放旧内存空间
	elements = newdata;
	first_free = dest;
	cap = elements + newcapacity;
}

void StrVec::reserve(const size_t& n)
{
	// 分配新内存
	auto newdata = alloc.allocate(n);
	// 将数据从旧内存移动到新内存
	auto dest = newdata;
	auto elem = elements;
	for (size_t i = 0; i != size(); ++i)
		alloc.construct(dest++, move(*elem++));
	free(); //完成移动后释放旧内存空间
	elements = newdata;
	first_free = dest;
	cap = elements + n;
}

void StrVec::resize(const size_t& n, const string& s = string())
{
	if (n < size())
	{
		for (auto it = elements + n; it != first_free; it++)
			alloc.destroy(it);
		alloc.deallocate(elements + n, size()-n);
	}
	else
	{
		for(int i = 0; i< n - size(); ++i)
			push_back(s);
	}
}

main.cpp

int main()
{
    fstream fin("infile.txt");
    TextQuery dict(fin);

    dict.QueryWord("you're");

    return 0;
}

Test 13.43

void StrVec::free()
{
	if (elements)
	{
		for_each(elements, first_free, [this](string& s) {alloc.destroy(&s); });
		//销毁所有元素
		//for (auto p = first_free; p != elements; )
		//	alloc.destroy(--p);
		//释放内存
		alloc.deallocate(elements, cap - elements);
	}
}

Test 13.44

String.h

#pragma once
#include<memory>
#include<utility>
using std::initializer_list;
using std::allocator;
using std::pair;

class String
{
public:
	// construct func
	String() : elements(nullptr), first_free(nullptr), cap(nullptr) {};
	String(const initializer_list<char>&);
	String(const char*);
	// copy control member
	String(const String&);
	String& operator=(const String&);
	~String() {};
	// member func
	void push_back(const char&);
	size_t size() const { return first_free - elements; }
	size_t capacity() const { return cap - elements; }
	char* begin() const { return elements; }
	char* end() const { return first_free; }
	void reserve(const size_t&);
	void resize(const size_t&, const char&);

	char getvalue(size_t index) { return *(elements + index); };

private:
	allocator<char> alloc; //为char元素分配内存
	void chk_n_alloc() { if (size() == capacity()) reallocate(); }; //如果大小等于容量,则重新分配空间
	pair<char*, char*> alloc_n_copy(const char*, const char*);
	void free(); //销毁元素并释放内存
	void reallocate(); //重新分配内存空间
	char* elements; // pointer to first element
	char* first_free; // pointer to the next pos of last element
	char* cap; // pointer to the next pos of alloc
};

String.cpp

#include"String.h"
#include<algorithm>
#include<iostream>
#include <typeinfo>
#include <type_traits>

using std::make_pair;
using std::uninitialized_copy;
using std::for_each;
using std::cout;
using std::endl;

String::String(const initializer_list<char>& sl)
{
	for (auto& s : sl)
		push_back(s);
}

String::String(const char* c)
{
	elements = alloc.allocate(strlen(c));
	first_free = elements + strlen(c);
	cap = first_free + strlen(c);
}

void String::push_back(const char& s)
{
	chk_n_alloc();
	alloc.construct(first_free++, s); //在first_free处添加元素s,并移动指针
}

pair<char*, char*> String::alloc_n_copy(const char* b, const char* e)
{
	//分配新空间
	auto data = alloc.allocate(e - b);
	//初始化并返回一个pair
	return make_pair(data, uninitialized_copy(b, e, data));
}

void String::free()
{
	if (elements)
	{
		for_each(elements, first_free, [this](char& s) {alloc.destroy(&s); });
		//销毁所有元素
		//for (auto p = first_free; p != elements; )
		//	alloc.destroy(--p);
		//释放内存
		alloc.deallocate(elements, cap - elements);
	}
}

String::String(const String& s)
{
	//调用alloc_n_copy分配空间以容纳与s中一样多的元素
	auto newdata = alloc_n_copy(s.begin(), s.end());
	elements = newdata.first;
	first_free = cap = newdata.second;

	cout << "do String(const String& s)" << endl;
}

String& String::operator=(const String& rhs)
{
	//调用alloc_n_copy分配空间以容纳与rhs中一样多的元素
	auto data = alloc_n_copy(rhs.begin(), rhs.end());
	free();
	elements = data.first;
	first_free = cap = data.second;

	cout << "do String& operator=(const String& rhs)" << endl;

	return *this;
}

void String::reallocate()
{
	// newcapacity表示当前内存空间的两倍大小
	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 String::reserve(const size_t& n)
{
	// 分配新内存
	auto newdata = alloc.allocate(n);
	// 将数据从旧内存移动到新内存
	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 + n;
}

void String::resize(const size_t& n, const char& s = char())
{
	if (n < size())
	{
		for (auto it = elements + n; it != first_free; it++)
			alloc.destroy(it);
		alloc.deallocate(elements + n, size() - n);
	}
	else
	{
		for (int i = 0; i < n - size(); ++i)
			push_back(s);
	}
}

Test 13.47

String::String(const String& s)
{
	//调用alloc_n_copy分配空间以容纳与s中一样多的元素
	auto newdata = alloc_n_copy(s.begin(), s.end());
	elements = newdata.first;
	first_free = cap = newdata.second;

	cout << "do String(const String& s)" << endl;
}

String& String::operator=(const String& rhs)
{
	//调用alloc_n_copy分配空间以容纳与rhs中一样多的元素
	auto data = alloc_n_copy(rhs.begin(), rhs.end());
	free();
	elements = data.first;
	first_free = cap = data.second;

	cout << "do String& operator=(const String& rhs)" << endl;

	return *this;
}

Test 13.48

int main()
{
    vector<String> svec;

    char a[] = "aaa";
    char b[] = "bbb";
    char c[] = "ccc";

    String stra(a);
    String strb(b);
    String strc(c);

    svec.push_back(stra);
    svec.push_back(strb);
    svec.push_back(strc);

    return 0;
}

输出结果:

do String(const String& s)
do String(const String& s)
do String(const String& s)
do String(const String& s)
do String(const String& s)
do String(const String& s)

共执行了6次拷贝构造函数

Test 13.49

Message类

class Message
{
	friend class Floder;
	friend void swap(Message&, Message&);
public:
	// construct func
	explicit Message(const string& str = "") : contents(str) {};
	// copy control members
	Message(const Message&);
	Message(Message&& m) :contents(std::move(m.contents)) { move_Floders(&m); };
	Message& operator=(const Message&);
	Message& operator=(Message&&);
	~Message();
	// member func
	void save(Floder&);
	void remove(Floder&);
	void addFld(Floder*);
	void remFld(Floder*);
private:
	string contents;
	set<Floder*> floders;
	void add_to_floders(const Message&);
	void remove_from_floders();
	void move_Floders(Message* m);
};
Message& Message::operator=(Message&& rhs)
{
	if (this != &rhs)
	{
		remove_from_floders();
		contents = std::move(rhs.contents);
		move_Floders(&rhs);
	}
	return *this;
}

StrVec类

class StrVec
{
public:
	// construct func
	StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) {};
	StrVec(const initializer_list<string>&);
	// copy control member
	StrVec(const StrVec&);
	StrVec(StrVec&&) noexcept;
	StrVec& operator=(const StrVec&);
	StrVec& operator=(StrVec&&) noexcept;
	~StrVec() {};
	// member func
	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(const size_t&, const string&);

	string& getvalue(size_t index) { return *(elements + index); };

private:
	allocator<string> alloc; //为string元素分配内存
	void chk_n_alloc() { if (size() == capacity()) reallocate(); }; //如果大小等于容量,则重新分配空间
	pair<string*, string*> alloc_n_copy(const string*, const string*);
	void free(); //销毁元素并释放内存
	void reallocate(); //重新分配内存空间
	string* elements; // pointer to first element
	string* first_free; // pointer to the next pos of last element
	string* cap; // pointer to the next pos of alloc
};
StrVec::StrVec(StrVec&& s) noexcept
{
	auto newdata = alloc_n_copy(s.begin(), s.end());
	elements = newdata.first;
	first_free = cap = newdata.second;
	s.elements = s.first_free = s.cap = nullptr;
}

StrVec& StrVec::operator=(StrVec&& rhs) noexcept 
{
	if (this != &rhs)
	{
		//调用alloc_n_copy分配空间以容纳与rhs中一样多的元素
		auto data = alloc_n_copy(rhs.begin(), rhs.end());
		free();
		elements = data.first;
		first_free = cap = data.second;
		rhs.elements = rhs.first_free = rhs.cap = nullptr;
	}
	
	return *this;
}

String类

class String
{
public:
	// construct func
	String() : elements(nullptr), first_free(nullptr), cap(nullptr) {};
	String(const initializer_list<char>&);
	String(const char*);
	// copy control member
	String(const String&);
	String(String&&) noexcept;
	String& operator=(const String&);
	String& operator=(String&&) noexcept;
	~String() {};
	// member func
	void push_back(const char&);
	size_t size() const { return first_free - elements; }
	size_t capacity() const { return cap - elements; }
	char* begin() const { return elements; }
	char* end() const { return first_free; }
	void reserve(const size_t&);
	void resize(const size_t&, const char&);

	char getvalue(size_t index) { return *(elements + index); };

private:
	allocator<char> alloc; //为char元素分配内存
	void chk_n_alloc() { if (size() == capacity()) reallocate(); }; //如果大小等于容量,则重新分配空间
	pair<char*, char*> alloc_n_copy(const char*, const char*);
	void free(); //销毁元素并释放内存
	void reallocate(); //重新分配内存空间
	char* elements; // pointer to first element
	char* first_free; // pointer to the next pos of last element
	char* cap; // pointer to the next pos of alloc
};
String::String(String&& s) noexcept
{
	//调用alloc_n_copy分配空间以容纳与s中一样多的元素
	auto newdata = alloc_n_copy(s.begin(), s.end());
	elements = newdata.first;
	first_free = cap = newdata.second;
	s.elements = s.cap = s.first_free = nullptr;

	cout << "do String(String&& s)" << endl;
}

String& String::operator=(String&& rhs) noexcept
{
	if (this != &rhs)
	{
		//调用alloc_n_copy分配空间以容纳与rhs中一样多的元素
		auto data = alloc_n_copy(rhs.begin(), rhs.end());
		free();
		elements = data.first;
		first_free = cap = data.second;
		rhs.elements = rhs.first_free = rhs.cap = nullptr;
	}

	cout << "do String& operator=(String&& rhs)" << endl;

	return *this;
}

Test 13.50

int main()
{
    vector<String> svec;

    char c1[] = "aaa";
    char c2[] = "bbb";
    String s1("ccc");
    String s3(s1);

    svec.push_back(s1);
    svec.push_back(std::move(s3));


    return 0;
}

输出结果:

do String(const String& s)
do String(const String& s)
do String(String&& s) noexcept
do String(String&& s) noexcept

Test 13.53

class HasPtr
{
	friend void swap(HasPtr&, HasPtr&);
public:
	HasPtr(const string& s = string()) : ps(new string(s)), i(0) {};
	HasPtr(const HasPtr& hp) : ps(new string(*hp.ps)), i(hp.i) {};
	HasPtr(HasPtr&& hp) noexcept  : ps(hp.ps), i(hp.i) { hp.ps = 0; };
	HasPtr& operator=(const HasPtr&);
	HasPtr& operator=(HasPtr&&) noexcept;
	bool operator<(const HasPtr&) const;

	string getstr() const;

private:
	string* ps;
	int i;
};
HasPtr& HasPtr::operator=(HasPtr&& rhs) noexcept
{
	if (this != &rhs)
	{
		delete ps;
		ps = rhs.ps;
		rhs.ps = 0;
		rhs.i = 0;
	}
	
	return *this;
}

Test 13.54

因为对于 hp2 = std::move(hp1);这样的赋值语句来说,两个运算符匹配的一样好,从而产生了二义性。

HasPtr hp1;
HasPtr hp2;

hp2 = std::move(hp1);

在这里插入图片描述

Test 13.55

class StrVec
{
public:
	//..... 
	void push_back(const string&);
	void push_back(string&&);
	//......
};
void StrVec::push_back(const string& s)
{
	chk_n_alloc();
	alloc.construct(first_free++, s); //在first_free处添加元素s,并移动指针
}

void StrVec::push_back(string&& s)
{
	chk_n_alloc();
	alloc.construct(first_free++, std::move(s)); //在first_free处添加元素s的右值,并移动指针
}

Test 13.58

Foo.h

#include<vector>
using namespace std;

class Foo
{
public:
	Foo sort() &&;
	Foo sort() const&;

private:
	vector<int> data;
};

Foo.cpp

#include<algorithm>
#include"Foo.h"

Foo Foo::sort() &&
{
	std::sort(data.begin(), data.end());
	return *this;
}
Foo Foo::sort() const & 
{
	Foo ret(*this);
	std::sort(ret.data.begin(), ret.data.end());
	return ret;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值