C++Primer第五版 习题答案(部分) 第十三章 拷贝控制

C++Primer第五版 习题答案(部分) 第十三章 拷贝控制,第1张

13.4
Point global;
Point foo_bar(Point arg) //1 函数参数
{
    Point local = arg, *heap = new Point(global); //2,3 赋值初始化
    *heap = local;
    Point pa[ 4 ] = { local, *heap }; //4,5 列表初始化
    return *heap; //6 返回值
}

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

13.8
class HasPtr {
public:
	HasPtr(const std::string& s = std::string()) : ps(new std::string(s)), i(0) { }
	HasPtr(const HasPtr& hp) :ps(new std::string(*hp.ps)),i(hp.i) {}
	HasPtr& operator=(const HasPtr& rhs_hp)
	{
		std::string* tmp_ps = new std::string(*rhs_hp.ps);
		delete ps;
		ps = tmp_ps;
		i = rhs_hp.i;
	}
private:
	std::string* ps;
	int i;
};
13.11
class HasPtr {
public:
	HasPtr(const std::string& s = std::string()) : ps(new std::string(s)), i(0) { }
	HasPtr(const HasPtr& hp) :ps(new std::string(*hp.ps)),i(hp.i) {}
	HasPtr& operator=(const HasPtr& rhs_hp)
	{
		if (this != &rhs_hp)
		{
			std::string* tmp_ps = new std::string(*rhs_hp.ps);
			delete ps;
			ps = tmp_ps;
			i = rhs_hp.i;
		}
		return *this;
		
	}
	~HasPtr()
	{
		delete ps;
	}

private:
	std::string* ps;
	int i;
};
13.13
#include 
#include 
#include 

struct X
{
	X() { std::cout << "X()" << std::endl; }
	X(const X&) { std::cout << "X(const X&)" << std::endl; }
	X& operator=(const X& rh)
	{
		std::cout << "X& operator=(const X &rh)" << std::endl;
		return *this;
	}
	~X() { std::cout << "~x()" << std::endl; }
};

void func1(X x)
{
	std::cout << "void func1(X x)" << std::endl;
}

void func2(X& x)
{
	std::cout << "void func2(X &x)" << std::endl;
}

int main()
{
	std::cout << "x1" << std::endl;
	X x1;
	func1(x1);
	std::cout << "main" << std::endl;
	func2(x1);
	std::cout << "main" << std::endl;
	X* x2 = new X();
	{
		std::cout << "vector" << std::endl;
		std::vector<X> v;
		v.reserve(2);
		v.push_back(x1);
		v.push_back(*x2);
	}
	delete x2;
	std::cout << "after delete x2" << std::endl;

	return 0;
}

13.17

13.14

#include 
#include 
#include 

class numbered
{
friend void f(numbered s);
public:
	numbered() : mysn(std::to_string(std::rand())) { };
	~numbered() { };
private:
	std::string mysn;
};

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

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

	return 0;
}

13.15

#include 
#include 
#include 

class numbered
{
friend void f(numbered s);
public:
	numbered() : mysn(std::to_string(std::rand())) { };
	numbered(const numbered&) : mysn(std::to_string(std::rand())) { };
	~numbered() { };
private:
	std::string mysn;
};

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

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

	return 0;
}

13.16

#include 
#include 
#include 

class numbered
{
friend void f(const numbered&);
public:
	numbered() : mysn(std::to_string(std::rand())) { };
	numbered(const numbered&) : mysn(std::to_string(std::rand())) { };
	~numbered() { };
private:
	std::string mysn;
};

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

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

	return 0;
}

13.18
#include 
#include 

class Employee
{
friend void print(const Employee& e);
public:
	Employee() { id = n; ++n; };
	Employee(const std::string& s) {
		id = n;
		++n; name = s;
	}

private:
	std::string name;
	int id;
	static int n;
};

void print(const Employee& e)
{
	std::cout << e.name << " " << e.id << std::endl;
}
int Employee::n = 0;

int main()
{
	Employee a;
	Employee b("aaaa");
	print(a);
	print(b);
	return 0;
}

13.26
StrBlob::StrBlob() : data(std::make_shared<std::vector<std::string>>()){}
StrBlob::StrBlob(std::initializer_list<std::string> il) : data(std::make_shared<std::vector<std::string>>(il)){}
StrBlob::StrBlob(const StrBlob &sb) { data = std::make_shared<std::vector<std::string>>(*sb.data); }
StrBlob &StrBlob::operator=(const StrBlob &sb) { data = std::make_shared<std::vector<std::string>>(*sb.data); return *this; }
13.27
#ifndef HASPTR_EX11_H
#define HASPTR_EX11_H

#include 

class HasPtr {
public:
    HasPtr(const std::string& s = std::string()) : ps(new std::string(s)), i(0), use(new std::size_t(1)) { }
    HasPtr(const HasPtr& hp) : ps(new std::string(*hp.ps)), i(hp.i) { ++* use; }  //递增计数器
    HasPtr& operator=(const HasPtr& rhs) {
        ++* rhs.use; //递增右侧运算对象的引用次数
        if (-- * use == 0)
        {
            delete ps;
            delete use;
        }
        ps = rhs.ps;
        i = rhs.i;
        use = rhs.use;
        return *this;  //返回本对象
    }
    ~HasPtr()
    {
        if (-- * use == 0) //计数器变为0
        {
            delete ps; //释放string
            delete use; //释放计数器
        }
    }
private:
    std::string* ps;
    int i;
    std::size_t* use;
};

#endif

13.28
#ifndef CP5_ex13_28_h
#define CP5_ex13_28_h

#include 
using std::string;

class TreeNode {
public:
    TreeNode() : value(string()), count(new int(1)), left(nullptr), right(nullptr) { }
    TreeNode(const TreeNode& rhs) : value(rhs.value), count(rhs.count), left(rhs.left), right(rhs.right) { ++* count; } 
    TreeNode& operator=(const TreeNode& rhs)
    {
        ++* rhs.count;
        if (-- * count == 0) {
            delete left;
            delete right;
            delete count;
        }
        value = rhs.value;
        left = rhs.left;
        right = rhs.right;
        count = rhs.count;
        return *this;
    }
    ~TreeNode() {
        if (-- * count == 0) {
            delete left;
            delete right;
            delete count;
        }
    }

private:
    std::string value;
    int* count;
    TreeNode* left;
    TreeNode* right;
};

class BinStrTree {
public:
    BinStrTree() : root(new TreeNode()) { }
    BinStrTree(const BinStrTree& bst) : root(new TreeNode(*bst.root)) { }
    BinStrTree& operator=(const BinStrTree& bst)
    {
        //行为像值的类
        TreeNode* new_root = new TreeNode(*bst_node);
        delete root;
        root = new_root;
        return *this;
    }
    ~BinStrTree() { delete root; }

private:
    TreeNode* root;
};

#endif

13.30


#include 
#include 

class HasPtr {
    friend void swap(HasPtr&, HasPtr&);
    friend bool operator<(const HasPtr&, const HasPtr&);
public:
    HasPtr(const std::string& s = std::string()) : ps(new std::string(s)), i(0) { }
    HasPtr(const HasPtr& hp) : ps(new std::string(*hp.ps)), i(hp.i) { }
    HasPtr& operator=(const HasPtr& rhs_hp) {
        auto newp = new std::string(*rhs_hp.ps);
        delete ps;
        ps = newp;
        i = rhs_hp.i;
        return *this;
    }
    ~HasPtr()
    {
        delete ps;
    }
private:
    std::string* ps;
    int i;
};

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

bool operator<(const HasPtr& lhs, const HasPtr& rhs)
{
    std::cout << "<" << std::endl;
    return *lhs.ps < *rhs.ps;
}


int main()
{
    HasPtr hp1("aaa"), hp2("bbb");
    swap(hp1, hp2);
    std::cout << "main" << std::endl;

    return 0;
}

13.31
#include
#include
#include 
#include 

class HasPtr {
    friend void swap(HasPtr&, HasPtr&);
    friend bool operator<(const HasPtr&, HasPtr&);
public:
    HasPtr(const std::string& s = std::string()) : ps(new std::string(s)), i(0) { }
    HasPtr(const HasPtr& hp) : ps(new std::string(*hp.ps)), i(hp.i) { }
    HasPtr& operator=(const HasPtr& rhs_hp) {
        auto newp = new std::string(*rhs_hp.ps);
        delete ps;
        ps = newp;
        i = rhs_hp.i;
        return *this;
    }
    ~HasPtr()
    {
        delete ps;
    }
private:
    std::string* ps;
    int i;
};

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

bool operator<(const HasPtr& lhs, HasPtr&rhs)
{
    std::cout << "<" << std::endl;
    return  *lhs.ps < *rhs.ps;
}

int main()
{
    HasPtr hp1("aaa"), hp2("bbb");
    swap(hp1, hp2);
    std::cout << "main" << std::endl;
    std::vector<HasPtr> vh{ hp1,hp2 };
    std::sort(vh.begin(), vh.end());
    return 0;
}

13.34
#ifndef MESSAGE_H_
#define MESSAGE_H_

#include 
#include 

class Message
{
	friend class Folder;
	friend void swap(Message&, Message&);
public:
	explicit Message(const std::string &str = "") : contents(str) { };
	Message(const Message&);
	Message& operator=(const Message&);
	~Message();
	void save(Folder&);
	void remove(Folder&);
private:
	std::string contents;
	std::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 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;
}

#endif

13.36
#include
#include

class Folder; //声明
class Message
{
	friend class Folder;
	friend void swap(Message&, Message&);
public:
	explicit Message(const std::string& str = "") :contents(str) {};
	Message(const Message&);
	Message& operator=(const Message&);
	~Message();
	void save(Folder&);
	void remove(Folder&);
private:
	std::string contents;
	std::set<Folder*> folders;
	void add_to_Floders(const Message&);
	void remove_from_Floders();
	void addFldr(Folder* f) { folders.insert(f); }
	void remFldr(Folder* f) { folders.erase(f); }
};

class Folder
{
	friend class Message;
	friend void swap(Folder&, Folder&);

public:
	Folder() = default;
	Folder(const Folder&);
	Folder& operator=(const Folder&);
	~Folder();
private:
	std::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 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_Floders(const Message& m)
{
	for (auto f : m.folders)
		f->addMsg(this);
}

Message::Message(const Message& m) :contents(m.contents), folders(m.folders) { add_to_Floders(m); }

void Message::remove_from_Floders()
{
	for (auto f : folders)
		f->remMsg(this);
}
Message::~Message()
{
	remove_from_Floders();
}

Message& Message::operator=(const Message& rhs)
{
	remove_from_Floders();
	contents = rhs.contents;
	folders = rhs.folders;
	add_to_Floders(rhs);
	return *this;
}

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()
{
	remove_from_Message();
}

Folder& Folder::operator=(const Folder& rhs)
{
	remove_from_Message();
	msgs = rhs.msgs;
	add_to_Message(rhs);
	return *this;
}
int main()
{
	return 0;
}

13.40
#include
#include
#include

class StrVec
{
public:
	StrVec() :elements(nullptr),first_free(nullptr),cap(nullptr) {}
	StrVec(std::initializer_list<std::string>);
	StrVec(const StrVec&);
	StrVec& operator=(const StrVec&);
	~StrVec();
	void push_back(const std::string&);
	size_t size()const { return first_free - elements; }
	size_t capacity()const { return cap - elements; }
	std::string* begin() const { return elements; };
	std::string* end() const { return first_free; };
	void reserve(size_t n);
	void resize(size_t n);
	void resize(size_t n, const std::string& s);
private:
	std::allocator<std::string> alloc;
	void check_n_alloc() { if (size() == capacity())reallocate(); }
	std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);
	void free();
	void reallocate();
	std::string* elements;
	std::string* first_free;
	std::string* cap;
};

StrVec::StrVec(std::initializer_list<std::string> i1)
{
	auto newdata = alloc_n_copy(i1.begin(), i1.end());
	elements = newdata.first;
	first_free = cap = newdata.second;
}

void StrVec::push_back(const std::string& s)
{
	check_n_alloc();
	alloc.construct(first_free++, s);
}

std::pair<std::string*, std::string*>StrVec::alloc_n_copy(const std::string* b, const std::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();
}

void StrVec::reserve(size_t n)
{
	if (n <= capacity())return;
	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 StrVec::resize(size_t n)
{
	resize(n, std::string());
}

void StrVec::resize(size_t n, const std::string& s)
{
	if (n < size())
	{
		while (n<size())
		{
			alloc.destroy(--first_free);
		}

	}
	else if (n > size())
	{
		while (n>size())
		{
			push_back(s);
		}
	}
}
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;
}

int main()
{
	StrVec s({ "aa","bb"});
	return 0;
}
13.43
std::for_each(elements, first_free, [this](std::string&p) {alloc.destroy(&p); });

第二种,更简洁;

13.44
#include
#include
#include

class String
{
public:
	String();
	String(const char*);
	String(const String&);
	String& operator=(const String&);
	char* begin()const { return elements; };
	char* end()const{return first_free;};
	~String();
private:
	std::pair<char*, char*> alloc_n_copy(const char*, const char*);
	void free();
	std::allocator<char> alloc;
	char* elements;
	char* first_free;
};

std::pair<char*, char*> String::alloc_n_copy(const char* begin, const char* end)
{
	char* p = alloc.allocate(end - begin);
	return { p,std::uninitialized_copy(begin,end,p) };
}
String::String(const char* cp)
{
	size_t n = strlen(cp);
	auto newstr = alloc_n_copy(cp, cp + n);
	elements = newstr.first;
	first_free = newstr.second;
}

String::String()
{
	String("");
}

String::String(const String& rhs)
{
	auto newstr = alloc_n_copy(rhs.begin(), rhs.end());
	elements = newstr.first;
	first_free = newstr.second;
}
void String::free()
{
	if (elements)
	{
		std::for_each(elements, first_free, [this](char cp) {alloc.destroy(&cp); });
		alloc.deallocate(elements, first_free - elements);
	}
}
String& String::operator=(const String& rhs)
{
	auto newstr = alloc_n_copy(rhs.begin(), rhs.end());
	free();
	elements = newstr.first;
	first_free = newstr.second;
	return *this;
}

String::~String()
{
	free();
}

int main()
{
	return 0;

}
13.48
#include
#include
#include
#include
#include

class String
{
public:
	String();
	String(const char*);
	String(const String&);
	String& operator=(const String&);
	char* begin()const { return elements; };
	char* end()const{return first_free;};
	~String();
private:
	std::pair<char*, char*> alloc_n_copy(const char*, const char*);
	void free();
	std::allocator<char> alloc;
	char* elements;
	char* first_free;
};

std::pair<char*, char*> String::alloc_n_copy(const char* begin, const char* end)
{
	char* p = alloc.allocate(end - begin);
	return { p,std::uninitialized_copy(begin,end,p) };
}
String::String(const char* cp)
{
	size_t n = strlen(cp);
	auto newstr = alloc_n_copy(cp, cp + n);
	elements = newstr.first;
	first_free = newstr.second;
}

String::String()
{
	String("");
}

String::String(const String& rhs)
{
	auto newstr = alloc_n_copy(rhs.begin(), rhs.end());
	elements = newstr.first;
	first_free = newstr.second;
	std::cout<<"String(const String& rhs)"<<std::endl;
}
void String::free()
{
	if (elements)
	{
		std::for_each(elements, first_free, [this](char cp) {alloc.destroy(&cp); });
		alloc.deallocate(elements, first_free - elements);
	}
}
String& String::operator=(const String& rhs)
{
	auto newstr = alloc_n_copy(rhs.begin(), rhs.end());
	free();
	elements = newstr.first;
	first_free = newstr.second;
	std::cout << "String::operator=(const String& rhs)" << std::endl;
	return *this;
}

String::~String()
{
	free();
}

int main()
{
	std::vector<String>v;
	v.push_back("aa");
	v.push_back("bbb");
	return 0;

}

显示被拷贝了3次(只拷贝了两次,vector有扩容)

13.49

StrVec

#ifndef STRVEC_H_
#define STRVEC_H_

#include 
#include 
#include 
#include 

class StrVec
{
public:
	StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) { }
	StrVec(std::initializer_list<std::string>);
	StrVec(const StrVec&);

	//移动构造函数
	StrVec(StrVec&& s)noexcept :
		alloc(std::move(s.alloc)),elements(std::move(s.elements)),first_free(std::move(s.first_free))
		, cap(std::move(s.cap)) {
		s.elements = s.first_free = s.cap = nullptr;
	}
	
	StrVec& operator=(const StrVec&);
	//移动赋值函数
	StrVec& operator=(StrVec&&)noexcept;

	~StrVec();
	void push_back(const std::string&);
	size_t size() const { return first_free - elements; }
	size_t capacity() const { return cap - elements; }
	std::string* begin() const { return elements; }
	std::string* end() const { return first_free; }
	void reserve(size_t n);
	void resize(size_t n);
	void resize(size_t n, const std::string& s);
private:
	std::allocator<std::string> alloc;
	void chk_n_alloc() { if (size() == capacity()) reallocate(); }
	std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);
	void free();
	void reallocate();
	std::string* elements;
	std::string* first_free;
	std::string* cap;
};

StrVec::StrVec(std::initializer_list<std::string> il)
{
	auto newdata = alloc_n_copy(il.begin(), il.end());
	elements = newdata.first;
	first_free = cap = newdata.second;
}

void StrVec::push_back(const std::string& s)
{
	chk_n_alloc();
	alloc.construct(first_free++, s);
}

std::pair<std::string*, std::string*> StrVec::alloc_n_copy(const std::string* b, const std::string* e)
{
	auto data = alloc.allocate(e - b);
	return { data, uninitialized_copy(b, e, data) };
}

void StrVec::free()
{
	if (elements)
	{
		std::for_each(elements, first_free, [this](std::string& p) { alloc.destroy(&p); });
		// 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();
}

void StrVec::reserve(size_t n)
{
	if (n <= capacity()) return;
	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 StrVec::resize(size_t n)
{
	resize(n, std::string());
}

void StrVec::resize(size_t n, const std::string& s)
{
	if (n < size())
	{
		while (n < size())
			alloc.destroy(--first_free);
	}
	else if (n > size())
	{
		while (n > size())
			push_back(s);
		// alloc.construct(first_free, s);
	}
}

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;
}

//移动赋值函数

StrVec& StrVec::operator=(StrVec&& rhs)noexcept
{
	if (this != &rhs)
	{
		free();
		alloc = std::move(rhs.alloc);
		elements = std::move(rhs.elements);
		first_free = std::move(rhs.first_free);
		cap = std::move(rhs.cap);
		rhs.elements = rhs.first_free = rhs.cap = nullptr;
	}

}

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;
}

#endif

String

#ifndef STRING_H_
#define STRING_H_

#include 
#include 
#include 
#include 

class String
{
public:
	String();
	String(const char*);
	String(const String&);

	//移动构造函数
	String(String&&)noexcept;
	
	String& operator=(const String&);

	//移动赋值函数
	String& operator=(String&&)noexcept;
	

	char* begin() const { return elements; }
	char* end() const { return first_free; }
	~String();
private:
	std::pair<char*, char*> alloc_n_copy(const char*, const char*);
	void free();

	std::allocator<char> alloc;
	char* elements;
	char* first_free;
};

std::pair<char*, char*> String::alloc_n_copy(const char* begin, const char* end)
{
	char* p = alloc.allocate(end - begin);
	// for(auto iter = begin; iter != end; ++iter)
	// 	alloc.construct(iter, *iter);
	return{ p, std::uninitialized_copy(begin, end, p) };
}

String::String(const char* cp)
{
	size_t n = strlen(cp);
	auto newstr = alloc_n_copy(cp, cp + n);
	elements = newstr.first;
	first_free = newstr.second;
	// char* p = alloc.allocate(n);

	// for(int i = 0; i < n; ++i)
	// 	alloc.construct(p+i, *(cp+i));
}

String::String()
{
	String("");
}

String::String(const String& rhs)
{
	auto newstr = alloc_n_copy(rhs.begin(), rhs.end());
	elements = newstr.first;
	first_free = newstr.second;
	std::cout << "String(const String &rhs)" << std::endl;
}

//移动构造函数

String::String(String&& s)noexcept :alloc(std::move(s.alloc)), elements(std::move(s.elements)),first_free(std::move(s.first_free))
{
	s.elements = s.first_free = nullptr;
}




void String::free()
{
	if (elements)
	{
		std::for_each(elements, first_free, [this](char cp) { alloc.destroy(&cp); });
		alloc.deallocate(elements, first_free - elements);
	}
}

String& String::operator=(const String& rhs)
{
	auto newstr = alloc_n_copy(rhs.begin(), rhs.end());
	free();
	elements = newstr.first;
	first_free = newstr.second;
	std::cout << "String& operator=(const String& rhs)" << std::endl;
	return *this;
}

//移动赋值函数
String& String::operator=(String&& rhs)noexcept
{
	if (&rhs != this)
	{
		free();
		alloc = std::move(rhs.alloc);
		elements = std::move(rhs.elements);
		first_free = std::move(rhs.first_free);
		rhs.elements = rhs.first_free = nullptr;

	}
	return *this;
}



String::~String()
{
	// for(auto iter = elements; iter != first_free; )
	// 	alloc.destroy(--iter);
	free();
}

#endif

Message

#ifndef MESSAGE_H_
#define MESSAGE_H_

#include 
#include 
#include 

class Folder;

class Message
{
	friend class Folder;
	friend void swap(Message&, Message&);
public:
	explicit Message(const std::string& str = "") : contents(str) { };
	Message(const Message&);
	
	//Messag移动构造函数
	Message(Message&& m) :contents(std::move(m.contents)) { move_Folders(&m); }
	
	Message& operator=(const Message&);

	//Messag移动赋值函数
	Message& operator=(Message&&);

	~Message();
	void save(Folder&);
	void remove(Folder&);
	void move_Folders(Message*);
private:
	std::string contents;
	std::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); }
};

class Folder
{
	friend void swap(Folder&, Folder&);
	friend class Message;
public:
	Folder() = default;
	Folder(const Folder&);
	Folder& operator=(const Folder&);
	~Folder();
private:
	std::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 Message::move_Folders(Message* m)
{
	folders = std::move(m->folders);
	for (auto f : folders)
	{
		f->remMsg(m);
		f->addMsg(this);
	}
	m->folders.clear();
}

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;
}

//Messag移动赋值函数
Message& Message::operator=(Message&& rhs)
{
	if (this != &rhs)
	{
		remove_from_Folders();
		contents = std::move(rhs.contents);
		move_Folders(&rhs);
	}
	return *this;
}



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()
{
	remove_from_Message();
}

Folder& Folder::operator=(const Folder& rhs)
{
	remove_from_Message();
	msgs = rhs.msgs;
	add_to_Message(rhs);
	return *this;
}

#endif

13.50
#include 
#include 
#include 
#include 
#include

class String
{
public:
	String();
	String(const char*);
	String(const String&);

	//移动构造函数
	String(String&&)noexcept;

	String& operator=(const String&);

	//移动赋值函数
	String& operator=(String&&)noexcept;


	char* begin() const { return elements; }
	char* end() const { return first_free; }
	~String();
private:
	std::pair<char*, char*> alloc_n_copy(const char*, const char*);
	void free();

	std::allocator<char> alloc;
	char* elements;
	char* first_free;
};

std::pair<char*, char*> String::alloc_n_copy(const char* begin, const char* end)
{
	char* p = alloc.allocate(end - begin);
	// for(auto iter = begin; iter != end; ++iter)
	// 	alloc.construct(iter, *iter);
	return{ p, std::uninitialized_copy(begin, end, p) };
}

String::String(const char* cp)
{
	size_t n = strlen(cp);
	auto newstr = alloc_n_copy(cp, cp + n);
	elements = newstr.first;
	first_free = newstr.second;
	// char* p = alloc.allocate(n);

	// for(int i = 0; i < n; ++i)
	// 	alloc.construct(p+i, *(cp+i));
}

String::String()
{
	String("");
}

String::String(const String& rhs)
{
	auto newstr = alloc_n_copy(rhs.begin(), rhs.end());
	elements = newstr.first;
	first_free = newstr.second;
	std::cout << "String(const String &rhs)" << std::endl;
}

//移动构造函数

String::String(String&& s)noexcept :alloc(std::move(s.alloc)), elements(std::move(s.elements)), first_free(std::move(s.first_free))
{
	std::cout << "String(const String &&rhs)" << std::endl;
	s.elements = s.first_free = nullptr;
}




void String::free()
{
	if (elements)
	{
		std::for_each(elements, first_free, [this](char cp) { alloc.destroy(&cp); });
		alloc.deallocate(elements, first_free - elements);
	}
}

String& String::operator=(const String& rhs)
{
	auto newstr = alloc_n_copy(rhs.begin(), rhs.end());
	free();
	elements = newstr.first;
	first_free = newstr.second;
	std::cout << "String& operator=(const String& rhs)" << std::endl;
	return *this;
}

//移动赋值函数
String& String::operator=(String&& rhs)noexcept
{
	std::cout << "String& operator=(const String&& rhs)" << std::endl;
	if (&rhs != this)
	{
		free();
		alloc = std::move(rhs.alloc);
		elements = std::move(rhs.elements);
		first_free = std::move(rhs.first_free);
		rhs.elements = rhs.first_free = nullptr;

	}
	return *this;
}



String::~String()
{
	// for(auto iter = elements; iter != first_free; )
	// 	alloc.destroy(--iter);
	free();
}

int main()
{
	std::vector<String>v1;
	v1.push_back("qqq");
	v1.push_back("bbb");
	return 0;
}

3次移动构造(其中一次vector扩容)

13.53

读取访问权限异常?!

#include
#include 
#include 
#include

class HasPtr {
    friend void swap(HasPtr&, HasPtr&);
    friend bool operator<(const HasPtr&, const HasPtr&);
public:
    HasPtr(const std::string& s = std::string()) : ps(new std::string(s)), i(0) { }
    HasPtr(const HasPtr& hp) : ps(new std::string(*hp.ps)), i(hp.i) { }
    //移动构造
    HasPtr( HasPtr&& hp)noexcept :ps(std::move(hp.ps)), i(std::move(hp.i)) { hp.ps = nullptr; }

  
    HasPtr& operator=(const HasPtr& rhs_hp) {
        auto newp = new std::string(*rhs_hp.ps);
        delete ps;
        ps = newp;
        i = rhs_hp.i;
        return *this;
    }

    //移动赋值
    HasPtr& operator=(HasPtr&& rhs_hp)noexcept
    {
        if (this != &rhs_hp)
        {
            delete ps;
            ps = std::move(rhs_hp.ps);
            i = std::move(rhs_hp.i);
        }
        return *this;
    
    }

   
    ~HasPtr()
    {
        delete ps;
    }
private:
    std::string* ps;
    int i;
};

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

bool operator<(const HasPtr& lhs, const HasPtr& rhs)
{
    std::cout << "<" << std::endl;
    return *lhs.ps < *rhs.ps;
}



int main()
{
    HasPtr hp1("aaa"), hp2("bbb");
    std::vector<HasPtr>vh{ hp1,hp2 };
    std::sort(vh.begin(), vh.end());
    return 0;

}
13.54

operator=不明确;

13.55

#include
#include 
#include 
#include 
#include 
#include 

class ConstStrBlobPtr;

class StrBlob
{
public:
	friend class ConstStrBlobPtr;
	typedef std::vector<std::string>::size_type size_type;
	StrBlob();
	StrBlob(std::initializer_list<std::string> il);
	StrBlob(const StrBlob&);
	StrBlob& operator=(const StrBlob&);
	size_type size() const { return data->size(); }
	bool empty() const { return data->empty(); }
	void push_back(const std::string& t) { data->push_back(t); std::cout << "push_back in left_value version" << std::endl;
	}

	//右值版本push_back
	void push_back(std::string&& t) { data->push_back(t); std::cout << "push_back in right_value version" << std::endl; }

	void pop_back();
	std::string& front();
	std::string& back();
	const std::string& front() const;
	const std::string& back() const;
	ConstStrBlobPtr begin();
	ConstStrBlobPtr end();
private:
	std::shared_ptr<std::vector<std::string>> data;
	void check(size_type i, const std::string& msg) const;
};

class ConstStrBlobPtr
{
public:
	ConstStrBlobPtr() : curr(0) {};
	ConstStrBlobPtr(const StrBlob& a, size_t sz = 0) : wptr(a.data), curr(sz) {}
	std::string& deref() const;
	ConstStrBlobPtr& incr();
private:
	std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string&) const;
	std::weak_ptr<std::vector<std::string>> wptr;
	std::size_t curr;
};

std::shared_ptr<std::vector<std::string>> ConstStrBlobPtr::check(std::size_t i, const std::string& msg) const
{
	auto ret = wptr.lock();
	if (!ret)
		throw std::runtime_error("unbound ConstStrBlobPtr");
	if (i >= ret->size())
		throw std::out_of_range(msg);
	return ret;
}

std::string& ConstStrBlobPtr::deref() const
{
	auto p = check(curr, "dereference past end");
	return (*p)[curr];
}

ConstStrBlobPtr& ConstStrBlobPtr::incr()
{
	check(curr, "increment past end of ConstStrBlobPtr");
	++curr;
	return *this;
}

StrBlob::StrBlob() : data(std::make_shared<std::vector<std::string>>()) {}
StrBlob::StrBlob(std::initializer_list<std::string> il) : data(std::make_shared<std::vector<std::string>>(il)) {}
StrBlob::StrBlob(const StrBlob& sb) { data = std::make_shared<std::vector<std::string>>(*sb.data); }
StrBlob& StrBlob::operator=(const StrBlob& sb) { data = std::make_shared<std::vector<std::string>>(*sb.data); return *this; }

void StrBlob::check(size_type i, const std::string& msg) const
{
	if (i >= data->size())
		throw std::out_of_range(msg);
}

std::string& StrBlob::front()
{
	check(0, "front on empty StrBlob");
	return data->front();
}

std::string& StrBlob::back()
{
	check(0, "back on empty StrBlob");
	return data->back();
}

const std::string& StrBlob::front() const
{
	check(0, "front on empty StrBlob");
	return data->front();
}

const std::string& StrBlob::back() const
{
	check(0, "back on empty StrBlob");
	return data->back();
}

void StrBlob::pop_back()
{
	check(0, "pop_back on empty StrBlob");
	data->pop_back();
}

ConstStrBlobPtr StrBlob::begin() { return ConstStrBlobPtr(*this); }

ConstStrBlobPtr StrBlob::end()
{
	auto ret = ConstStrBlobPtr(*this, data->size());
	return ret;
}

int main()
{
	StrBlob b1 = { "aa","a" };
	b1.push_back("aa");
	return 0;

13.58
#include
#include
#include

class Foo
{
public:
	Foo sorted()&&; //右值
	Foo sorted() const&; ///左值引用
private:
	std::vector<int >data;
};

Foo Foo::sorted()&&
{
	std::cout << "Foo::sorted()&&" << std::endl;
	sort(data.begin(), data.end());
	return *this;
}
Foo Foo::sorted()const&
{
	std::cout << "Foo::sorted()const&" << std::endl;

	/*Foo ret(*this);
	return ret.sorted()*/;
	//死循环

	return Foo(*this).sorted();
	
}

int main()
{
	Foo foo;
	foo.sorted();
	return 0;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/563309.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-02
下一篇 2022-04-02

发表评论

登录后才能评论

评论列表(0条)

保存