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也是一个好习惯。