前言:
难点:
通过下标访问字符串元素的基本思路重载[]运算符,在函数中直接返回该位置指针的解引用,但此时返回值为char类型,对于进行单个字符串修改的操作,如:str[1]='H';,无法处理赋值时的写时复制操作,只能通过输出流运算符输出char。
解决方法:
可以在CowString类内嵌套设置一个代理类,CowString的重载[]函数只需要返回该代理类CharProxy该代理类重载输出流运算符和赋值运算符,代理类进行后续操作的进行。
嵌套类权限:内部类相当于是定义在外部类中的外部类的友元类
#include <iostream>
#include <cstring>
using std::cout;
using std::endl;
using std::ostream;
class CowString
{
class CharProxy // 代理
{
public:
CharProxy(CowString &self, const size_t idx)
: _self(self), _idx(idx)
{
}
bool operator=(char ch);
friend ostream &operator<<(ostream &os, const CharProxy &rhs);
//CharProxy为私有内部类,该函数需要在内外部类中同时声明友元
private:
CowString &_self;
size_t _idx;
};
public:
CowString();
~CowString();
CowString(const CowString &rhs);
CowString(const char *pstr);
CowString &operator=(const CowString &rhs);
CharProxy operator[](size_t idx);
const char *c_str() { return _pstr; };
size_t size() const { return strlen(_pstr); };
int use_count() { return *(int *)(_pstr - refCountLength); };
friend ostream &operator<<(ostream &os, const CowString &rhs);
friend ostream &operator<<(ostream &os, const CharProxy &rhs);
private:
char *_pstr;
static const int refCountLength = 4;
};
// 构造
CowString::CowString()
: _pstr(new char[refCountLength + 1]())
{
*(int *)_pstr = 1; // 引用计数置为1
_pstr += refCountLength; // 后移至数据存放头
}
CowString::CowString(const CowString &rhs)
: _pstr(rhs._pstr)
{
++*(int *)(_pstr - refCountLength);
}
CowString::CowString(const char *pstr)
: _pstr(new char[refCountLength + 1 + strlen(pstr)])
{
*(int *)_pstr = 1; // 引用计数置为1
_pstr += refCountLength;
strcpy(_pstr, pstr);
}
CowString &CowString::operator=(const CowString &rhs)
{
if (&rhs != this) // 非自复制
{
--*(int *)(_pstr - refCountLength);
if (*(int *)(_pstr - refCountLength) == 0)
{
delete[] (_pstr - refCountLength);
_pstr = nullptr;
}
_pstr = rhs._pstr;
++*(int *)(_pstr - refCountLength);
}
}
CowString::CharProxy CowString::operator[](size_t idx)
{
return CharProxy(*this, idx);
}
// 析构
CowString::~CowString()
{
--*(int *)(_pstr - refCountLength);
if (*(int *)(_pstr - refCountLength) == 0)
{
delete[] (_pstr - refCountLength);
_pstr = nullptr;
}
}
ostream &operator<<(ostream &os, const CowString &rhs)
{
os << rhs._pstr;
return os;
}
// 代理类实现
bool CowString::CharProxy::operator=(char ch)
{
if (_idx < _self.size())
{
if (_self.use_count() > 1)
{
// 深拷贝
char *ptemp = new char[refCountLength + 1 + strlen(_self._pstr)]();
ptemp += refCountLength;
strcpy(ptemp, _self._pstr);
// 原堆空间字符串引用计数减一
--*(int *)(_self._pstr - refCountLength);
if (*(int *)(_self._pstr - refCountLength) == 0)
{
delete[] (_self._pstr - refCountLength);
_self._pstr = nullptr;
}
// 修改指向
_self._pstr = ptemp;
// 初始化引用计数
*(int *)(_self._pstr - _self.refCountLength) = 1;
// 写入字符
*(_self._pstr + _idx) = ch;
return true;
}
}
else
{
cout << "out of range" << endl;
return false;
}
}
ostream &operator<<(ostream &os, const CowString::CharProxy &rhs)
{
if (rhs._idx < rhs._self.size())
{
os << *(rhs._self._pstr + rhs._idx);
return os;
}
else
{
cout << "out of range" << endl;
return os;
}
}
标签:pstr,self,CowString,C++,char,refCountLength,._,写时
From: https://blog.csdn.net/weixin_73809064/article/details/143753833