第十三章 习题13-21-习题13-30

习题13-21

不需要,因为都是用的智能指针,不需要析构函数,合成的拷贝控制成员已经满足要求,拷贝控制成员没有必要;

习题13-22

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

习题13-23

没有差异

习题13-24

如果未定义析构函数,默认合成的析构函数会导致动态内存无法释放;

如果未定义拷贝构造函数,会默认将数据成员依次赋值拷贝,导致指针互相拷贝,从而指向同一内存;

习题13-25

拷贝构造函数和拷贝赋值运算符必须重新分配动态内存;不需要析构函数,因为智能指针的动态内存是自动分配的;

习题13-26

#pragma once
#include<vector>
#include<string>
#include<initializer_list>
#include<memory>
#include<stdexcept>
using namespace std;
class StrBlobPtr;
class StrBlob {
	friend class StrBlobPtr;
public:
	typedef vector<string>::size_type size_type;
	StrBlob();
	StrBlob(initializer_list<string> il);
	StrBlob(vector<string> *p);
	StrBlob(StrBlob &s);
	StrBlob &operator=(StrBlob &rhs);
	size_type size() const { return data->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();
	StrBlobPtr begin() const;
	StrBlobPtr end()const;
private:
	shared_ptr<vector<string>> data;
	void check(size_type i, const string &msg) const;
};
inline StrBlob::StrBlob() :data(make_shared<vector<string>>()) {  }
inline StrBlob::StrBlob(initializer_list<string> il):
	data(make_shared<vector<string>>(il)){}
inline StrBlob::StrBlob(vector<string> *p):data(p){}
inline StrBlob::StrBlob(StrBlob &s):data(make_shared<vector<string>>(*s.data)){}
inline StrBlob &StrBlob::operator=(StrBlob &rhs)
{
	data = make_shared<vector<string>>(*rhs.data);
	return *this;
}
inline void StrBlob::check(size_type i, const string &msg)const
{
	if (i >= data->size())
		throw out_of_range(msg);
}
inline string &StrBlob::front()
{
	check(0, "front on empty StrBlob");
	return data->front();
}
inline const string &StrBlob::front() const
{
	check(0, "front on empty StrBlob");
	return data->front();
}
inline string&StrBlob::back()
{
	check(0, "back on empty StrBlob");
	return data->back();
}
inline const string&StrBlob::back()const
{
	check(0, "back on empty StrBlob");
	return data->back();
}
inline void StrBlob::pop_back()
{
	check(0, "pop_back on empty StrBlob");
	data->pop_back();
}

class StrBlobPtr
{
	friend bool eq(const StrBlobPtr &, const StrBlobPtr&);
public:
	StrBlobPtr() :curr(0) {}
	StrBlobPtr(StrBlob &a, size_t sz=0):wptr(a.data),curr(sz){}
	StrBlobPtr(const StrBlob &a,size_t sz=0):wptr(a.data),curr(sz){}
	string &deref()const;
	string &deref(int off)const;
	StrBlobPtr &incr();
private:
	shared_ptr<vector<string>> check(size_t, const string &)const;
	weak_ptr<vector<string>> wptr;
	size_t curr;
};
inline shared_ptr<vector<string>> StrBlobPtr::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;
}
inline string &StrBlobPtr::deref()const
{
	auto p = check(curr, "dereference past end");
	return (*p)[curr];
}
inline string &StrBlobPtr::deref(int off)const
{
	auto p = check(curr + off, "dereference past end");
	return (*p)[curr + off];
}
inline StrBlobPtr &StrBlobPtr::incr()
{
	check(curr, "increment past end of StrBlobPtr");
	++curr;
	return *this;
}
inline StrBlobPtr StrBlob::begin()
{
	return StrBlobPtr(*this);
}

inline StrBlobPtr StrBlob::end()
{
	auto ret = StrBlobPtr(*this, data->size());
	return ret;
}
inline StrBlobPtr StrBlob::begin()const
{
	return StrBlobPtr(*this);
}

inline StrBlobPtr StrBlob::end()const
{
	auto ret = StrBlobPtr(*this, data->size());
	return ret;
}
inline bool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
	auto l = lhs.wptr.lock(), r = rhs.wptr.lock();
	if (l == r)
		return (!r || lhs.curr == rhs.curr);
	else
		return false;
}
inline bool neq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
	return !eq(lhs, rhs);
}

习题3-27

class HasPtr
{
	HasPtr(const string &s=string()):ps(new string(s)),i(0),use(new size_t(1)){}
	HasPtr(const HasPtr &p):ps(p.ps),i(p.i),use(p.use){++*use}
	HasPtr &operator=(const HasPtr&);
	HasPtr &operator=(const string &);
	string &operator *();
	~HasPtr();
private:
	string *ps;
	int i;
	size_t *use;
};
HasPtr::~HasPtr()
{
	if (--*use == 0)
	{
		delete ps;
		delete use;
	}
}
HasPtr &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& HasPtr::operator=(const string &rhs)
{
	*ps = rhs;
	return *this;
}
string &HasPtr::operator*()
{
	return *ps;
}

习题13-28

书上的count没有解引用符号,二叉树不太会,答案中把count前面加了一个解引用符号,做法与习题13-27类似

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);
	~TreeNode()
	{
		if (--*count == 0)
		{
			if (left)
			{
				delete left;
				left = nullptr;
			}
			if (right)
			{
				delete right;
				right = nullptr;
			}
			delete count;
			count = nullptr;
		}
	}

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

TreeNode& TreeNode::operator=(const TreeNode &rhs)
{
	++*rhs.count;
	if (--*count == 0)
	{
		if (left)
		{
			delete left;
		}
		if (right)
		{
			delete right;
		}

		delete count;
	}
	value = rhs.value;
	left = rhs.left;
	right = rhs.right;
	count = rhs.count;
	return *this;
}


class BinStrTree
{
public:
	BinStrTree() : root(new TreeNode()) {}
	BinStrTree(const BinStrTree &bst) : root(new TreeNode(*bst.root)) {}
	BinStrTree& operator=(const BinStrTree &bst);
	~BinStrTree() { delete root; }

private:
	TreeNode *root;
};

BinStrTree& BinStrTree::operator=(const BinStrTree &bst)
{
	TreeNode *new_root = new TreeNode(*bst.root);
	delete root;
	root = new_root;
	return *this;
}


#endif

习题13-29

这里调用的参数是ps和i,分别为指针和整型,匹配到的swap函数是std::swap而不是swap(HasPtr &,HasPtr &),所以不会导致递归;

习题13-30

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值