String的写时拷贝
class String
{
protected:
struct StrNode
{
int ref;
int len;
int size;
char data[];
};
private:
StrNode* pstr;
public:
String(const char* p = NULL)
{
if (p != NULL)
{
int sz = strlen(p);
pstr = (StrNode*)malloc(sizeof(StrNode) + sz * 2 + 1);
pstr->ref = 1;
pstr->len = sz;
pstr->size = sz * 2;
strcpy(pstr->data, p);
}
}
~String()
{
if (pstr != NULL && --pstr->ref == 0)
{
free(pstr);
}
pstr = NULL;
}
String(const String& str) :pstr(NULL)
{
if (str.pstr != NULL)
{
pstr = str.pstr;
pstr->ref += 1;
}
}
String& operator=(const String& s)
{
if (this == &s)return *this;
if (this->pstr != NULL && --this->pstr->ref == 0)
{
free(this->pstr);
}
this->pstr = s.pstr;
if (this->pstr != NULL)
{
this->pstr->ref += 1;
}
return *this;
}
char& operator[](const int index)
{
if (pstr == NULL)exit(0);
assert(index >= 0 && index <= this->pstr->len - 1);
if (pstr->ref == 1)
{
return pstr->data[index];
}
else
{
int total = sizeof(StrNode) + pstr->size + 1;
StrNode* newnode = (StrNode*)malloc(total);
memmove(newnode, pstr, total);
newnode->ref = 1;
pstr->ref -= 1;
this->pstr = newnode;
return pstr->data[index];
}
}
const char& operator[](const int index)const
{
return (*const_cast<String*>(*this))[index];
}
ostream& operator<<(ostream& out)const
{
if (pstr != NULL)
{
out << pstr->data;
}
return out;
}
};
ostream& operator<<(ostream& out, const String& s)
{
s << out;
return out;
}
int main()
{
String s1("123456");
String s2(s1);
String s3("hello");
String s4(s3);
s1[0] = 'x';
cout << s2 << endl;
return 0;
}
当我们需要对公用数组的多个对象中的一个进行修改的时候,需要创建空间进行深拷贝,使其独立成为一个新的对象,在进行修改
在我们调用常方法的[] 运算符重载时,会发生常方法无法调用普通方法而导致的无限调用自身,return (*this)[index] ;而我们通过强制的手段,将this指针改为非常性使得正确调用普通方法
移动拷贝与移动赋值
String(String&& s):pstr(NULL)
{
this->pstr = s.pstr;
s.pstr = NULL;
}
String& operator=(String&& s)
{
if (this != &s)
{
if (pstr != NULL && --pstr->ref == 0)
{
free(pstr);
}
this->pstr = s.pstr;
s.pstr = NULL;
}
return *this;
}
写时拷贝的改进
每当我们通过调用中括号重载时 operator[]() ,都会产生新的空间,即使我们不需要改写,仅仅是进行获取
接下来我们对其进行改进
char operator[](const int index) const
{
assert(pstr != NULL && index >= 0 && index <= pstr->len-1);
return pstr->data[index];
}
void modify(const int index, const char ch)
{
assert(pstr != NULL && index >= 0 && index <= pstr->len - 1);
if (pstr->ref > 1)
{
int total = sizeof(StrNode) + pstr->size + 1;
StrNode* newnode = (StrNode*)malloc(total);
memmove(newnode, pstr, total);
newnode->ref = 1;
pstr->ref -= 1;
this->pstr = newnode;
}
pstr->data[index] = ch;
}
添加修改函数来实现修改的需求
String加法重载
const String operator+(const String& s)const
{
if (this->pstr == NULL && s.pstr == NULL)
{
return String();
}
else if (pstr != NULL && s.pstr == NULL)
{
return *this;
}
else if (pstr != NULL && s.pstr == NULL)
{
return s;
}
else
{
int total = (pstr->len + s.pstr->len) * 2;
StrNode* newsp = (StrNode*)malloc(sizeof(StrNode) + total + 1);
strcpy(newsp->data, pstr->data);
strcat(newsp->data, s.pstr->data);
newsp->ref = 1;
newsp->len = pstr->len + s.pstr->len;
newsp->size = total;
return String(newsp);
}
}
String加等重载
String& operator+=(const String& s)
{
if (this->pstr != NULL && s.pstr != NULL)
{
if (this->pstr->ref > 1)
{
int total = this->pstr->len + s.pstr->len;
this->pstr->ref -= 1;
char* tmp = this->pstr->data;
this->pstr = (StrNode*)malloc(sizeof(StrNode) + total * 2 + 1);
strcpy(this->pstr->data, tmp);
strcat(this->pstr->data, s.pstr->data);
this->pstr->ref = 1;
this->pstr->len = total; this->pstr->size = total*2;
}
else
{
if (this->pstr->size >= this->pstr->len + s.pstr->len)
{
strcat(this->pstr->data, s.pstr->data);
this->pstr->len = this->pstr->len + s.pstr->len;
}
else
{
int total = this->pstr->len + s.pstr->len;
this->pstr = (StrNode*)realloc(this->pstr, sizeof(StrNode) + total * 2 + 1);
strcat(this->pstr->data, s.pstr->data);
this->pstr->len = total;
}
}
return *this;
}
if (s.pstr == NULL)
{
return *this;
}
else if (pstr == NULL && s.pstr != NULL)
{
pstr = s.pstr;
pstr->ref += 1;
return *this;
}
}
|