C++ Primer 第十三章 拷贝控制 HasPtr的类值版本和类指针版本,以及StrBlob的拷贝控制成员

HasPtr的类值版本

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() { delete ps; }
	HasPtr& operator=(const HasPtr&);
	HasPtr& operator=(const string&);
	string& operator*() { return *ps; }
private:
	string* ps;
	int i;
};

HasPtr& HasPtr::operator=(const string& s)
{
	*ps = s;
	return *this;
}

HasPtr& HasPtr::operator=(const HasPtr& h)
{
	// 考虑自赋值情况,要融合析构和拷贝构造的功能
	string* backup = new string(*h.ps);
	delete ps;
	ps = backup;
	i = h.i;
	return *this;
}

HasPtr的类指针版本

class HasPtr
{
	friend ostream& operator<<(ostream&, const HasPtr&);
public:
	HasPtr(const string& s = string()) :ps(new string(s)), i(0), count(new int(1)) {}
	HasPtr(const HasPtr& h) :ps(h.ps), i(h.i), count(h.count) { ++* count; }
	~HasPtr();
	HasPtr& operator=(const HasPtr&);
	HasPtr& operator=(const string& s) { *ps = s; return *this; }
	string& operator*() { return *ps; }
private:
	string* ps;
	int i;
	int* count;
};

ostream& operator<<(ostream& os, const HasPtr& h)
{
	os << *h.ps;
	return os;
}

HasPtr::~HasPtr()
{
	if (-- *count == 0)
	{
		delete ps;
		delete count;
	}
}

HasPtr& HasPtr::operator=(const HasPtr& h)
{
	++* h.count;
	if (-- * count == 0)
	{
		delete ps;
		delete count;
	}
	ps = h.ps;
	i = h.i;
	count = h.count;
	return *this;
}

拷贝赋值运算符通常要结合析构函数和拷贝构造函数的功能,且要考虑自赋值的情况。

类值版本里的备份指针以及类指针版本里的先加赋值符右边对象的引用计数都是为了防止自赋值的情况,且要注意释放被赋值对象的动态资源。

 StrBlob的控制成员实现

class StrBlob
{
	//friend class StrBlobPtr;
public:
	using size_type = vector<string>::size_type;
	StrBlob();
	StrBlob(initializer_list<string> il);
	StrBlob(vector<string>* p);
	StrBlob(const StrBlob& s);
	StrBlob& operator=(const StrBlob& ths);
	~StrBlob() = default;
	// 实用性成员函数
	size_type size()const { return data->size(); }
	bool empty()const { return data->empty(); }
	//添加和删除元素
	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的接口
	//StrBlobPtr begin();
	//StrBlobPtr end();
	重载版本
	//StrBlobPtr begin()const;
	//StrBlobPtr end()const;
private:
	void check(size_type i, const string& msg)const;
private:
	shared_ptr<vector<string>> data;  //data智能指针指向一个vector<string>>
};

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(const StrBlob& s) : data(make_shared<vector<string>>(*s.data)) {} // 拷贝构造函数
inline StrBlob& StrBlob::operator=(const StrBlob& s)  // 重载拷贝赋值运算符
{
	// data = new vector<string>(*s.data);   // error
	data = make_shared<vector<string>>(*s.data);
	return *this;
}

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

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

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

拷贝构造函数和拷贝赋值运算符是新增的,并不复杂,还是得益于智能指针的运用。且因此析构函数也可以使用默认的了。

拷贝赋值运算符第一行注释。。。即智能指针不能直接用new返回的指针赋值,在构造函数初始化列表中对智能指针初始化时,用make_shared不用new也是一个好习惯。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值