C++ Primer(第五版) 12.1.5--12.1.6节练习

这篇博客探讨了C++ Primer第五版中关于unique_ptr的部分,强调了unique_ptr的不可拷贝和不可赋值特性,解释了为何这样设计以及在实际使用中如何进行对象所有权的转移。同时,通过举例说明了unique_ptr和shared_ptr在所有权管理上的区别。此外,还介绍了如何在StrBlob和StrBlobPtr的实现中应用unique_ptr。

12.16    对unique_ptr进行拷贝或赋值,程序会调用删除的函数,标准库为了禁止unique_ptr的拷贝和赋值,将其拷贝构造函数和赋值函数声明为delete的。

12.17   (a) 不合法。unique_ptr需要用指针初始化,int无法转换为指针;(b)合法;(c)合法;(d)合法;(e)合法;(f)合法

12.18    unique_ptr独占对象所有权,无法拷贝和赋值,需要用release操作从一个unique_ptr转移到另一个unique_ptr;shared_ptr共享对象所有权,支持拷贝和赋值,无需release操作。

12.19   将StrBlob和StrBlobPtr定义到头文件StrBlob.h中,代码如下

#ifndef STRBLOB_H
#define STRBLOB_H

#include <string>
#include <vector>
#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);
	bool empty() const { return data->empty(); }
	size_type size() const { return data->size(); }
	void push_back(const string &s) { data->push_back(s); }
	void pop_back();
	string& front();
	const string& front() const;
	string& back();
	const string& back() const;
	StrBlobPtr begin();
	StrBlobPtr end();
private:
	shared_ptr<vector<string>> data;
	void check(size_type i, const string &msg) const;
};

class StrBlobPtr {
	friend bool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs);
public:
	StrBlobPtr(): curr(0) { }
	StrBlobPtr(StrBlob &a, size_t sz = 0):
		wptr(a.data), curr(sz) { }
	string& deref() const;
	StrBlobPtr& incr();
private:
	shared_ptr<vector<string>> check(size_t, const string&) const;
	weak_ptr<vector<string>> wptr;
	size_t curr;
};

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

StrBlob::StrBlob(): data(make_shared<vector<string>>()) { }

StrBlob::StrBlob(initializer_list<string> il): data(make_shared<vector<string>>(il)) { }

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

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

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

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

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

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

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

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

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

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

inline
bool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
	shared_ptr<vector<string>> 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);
}
	

#endif

12.20    使用StrBlob.h进行测试,代码如下

#include <iostream>
#include <fstream>
#include "StrBlob.h"

using namespace std;

int main(int argc, char *argv[])
{
	ifstream in(argv[1]);
	string line;
	StrBlob sblob;
	
	while (getline(in, line)) {
		sblob.push_back(line);
	}
	
	StrBlobPtr sptr(sblob);
	for (sptr = sblob.begin(); neq(sptr, sblob.end()); sptr.incr())
		cout << sptr.deref() << endl;
	
	return 0;
}

12.21    使用如下定义可读性更好:

auto p = check(curr, "dereference past end");
	return (*p)[curr];

12.22   StrBlob.h修改如下

#ifndef STRBLOB_H
#define STRBLOB_H

#include <string>
#include <vector>
#include <memory>
#include <stdexcept>

using namespace std;

class ConstStrBlobPtr;

class StrBlob {
	friend class ConstStrBlobPtr;
public:
	typedef vector<string>::size_type size_type;
	StrBlob();
	StrBlob(initializer_list<string> il);
	bool empty() const { return data->empty(); }
	size_type size() const { return data->size(); }
	void push_back(const string &s) { data->push_back(s); }
	void pop_back();
	string& front();
	const string& front() const;
	string& back();
	const string& back() const;
	ConstStrBlobPtr begin() const;
	ConstStrBlobPtr end() const;
private:
	shared_ptr<vector<string>> data;
	void check(size_type i, const string &msg) const;
};

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

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

StrBlob::StrBlob(): data(make_shared<vector<string>>()) { }

StrBlob::StrBlob(initializer_list<string> il): data(make_shared<vector<string>>(il)) { }

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

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

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

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

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

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

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

shared_ptr<vector<string>>
ConstStrBlobPtr::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;
}

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

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

inline
bool eq(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)
{
	shared_ptr<vector<string>> l = lhs.wptr.lock(), r = rhs.wptr.lock();
	
	if (l == r)
		return (!r || lhs.curr == rhs.curr);
	else 
		return false;
}

inline 
bool neq(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)
{
	return !eq(lhs, rhs);
}
	

#endif

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值