>1.本次实现string为写实拷贝版本,参照new[]的形式,我们每次实现申请空间时,多在前面开辟4个字节来存放我们的引用计数,所谓的引用计数就是记录当前空间有多少对象在使用。也就是浅拷贝的形式。
>2.为了完善string的实现,我们在不进行修改当前空间时,多个对象可以对公用的空间读取,我们采用浅拷贝的形式对这块空间管理,引用计数的值代表当前空间有多少对象在使用,没有一个对象交出主动权,引用计数减少一个,每当有一个空间对其管理,引用计数增加一个。
>3.当我们所需要的对象对这块空间进行写操作的时候,我们需要进行深拷贝,为此对象单独开辟自己的空间来完成写入操作。
>4.此次的模拟实现没有考虑到多线程的场景,在必要的使用是,多个对象对一块空间进行管理的时候,我们需要的是进行加锁操作,来保证数据不会出错。
>5.对Checkreallocate()函数进行封装,来检测当进行写入操作时,当前空间需不要重新开辟。
#include<iostream>
#include<assert.h>
#include<string>
using namespace std;
class String
{
public:
String(const char* ptr = "")
:_size(strlen(ptr))
{
_capacity = _size;
_str = new char[_size + 5];
*(int*)_str = 1;
strcpy((_str + 4), ptr);
}
String(const String& s)
:_str(s._str)
, _size(s._size)
, _capacity(s._capacity)
{
(*(int*)_str)++;
}
String& operator=(const String& s)
{
if (_str != s._str)
{
release();
_str = s._str;
(*(int*)_str)++;
_size = s._size;
_capacity = s._capacity;
}
return *this;
}
~String()
{
release();
}
void release()
{
if (--(*(int*)_str) == 0)
{
(char*)_str;
delete[] _str;
_str = NULL;
}
}
void Checkreallocate()
{
if (*(int*)_str>1)
{
(*(int*)_str)--;
char* tmp = new char[_capacity + 5];
*(int*)tmp = 1;
strcpy((tmp - 4), (_str-4));
_str = tmp;
}
}
void Insert(size_t pos, char s)
{
assert(pos<_size);
if (_size == _capacity)
{
Expand(_capacity * 2);
}
size_t end = _size;
while (end >= pos)
{
(_str + 4)[end + 1] = (_str + 4)[end];
end--;
}
(_str + 4)[pos] = s;
_size++;
}
void Insert(size_t pos, const char* str)
{
size_t len = strlen(str);
Expand(len + _size);
size_t end = _size;
while (end >= pos)
{
(_str + 4)[end + len] = (_str + 4)[end];
end--;
}
size_t index = 0;
while (len>index)
{
(_str + 4)[pos + index] = str[index];
index++;
len--;
}
_size += len;
}
void Append(const char* str)
{
Insert(_size, str);
}
void Swap(String& s)
{
Checkreallocate();
swap(_str, s._str);
swap(_size, s._size);
swap(_capacity, s._capacity);
}
void Expand(size_t n)
{
if (n>_capacity)
{
if (*(int*)_str>1)
{
*(int*)_str--;
}
char* tmp = new char[n + 5];
_capacity = n;
*(int*)_str = 1;
strcpy((tmp - 4), _str);
_str = tmp;
}
}
char& operator[](size_t pos)
{
assert(pos<_size);
Checkreallocate();
return (_str + 4)[pos];
}
String operator+(const String& s)
{
String tmp(*this);
tmp.Insert(_size, (s._str + 4));
return tmp;
}
String& operator+=(const String& s)
{
Checkreallocate();
Insert( _size,(s._str+4));
return *this;
}
void Erase(size_t pos, size_t n)
{
assert(pos<_size);
Checkreallocate();
if (pos + n<_size)
{
size_t index = pos;
while (index + n <= _size)
{
(_str + 4)[index] = (_str + 4)[index + n];
index++;
}
}
else
{
(_str + 4)[pos] = 0;
}
_size -= n;
}
void PushBack(char s)
{
Insert(_size, s);
}
void PopBack()
{
assert(_size>0);
Erase(_size - 1, 1);
}
bool operator<(const String& s)
{
char* str1 = (_str + 4);
char* str2 = (_str + 4);
while (*str1&&*str2)
{
if (*str1<*str2)
return true;
else if (*str1>*str2)
return false;
else
{
str1++;
str2++;
}
}
if (*str2 == '/0')
return false;
else
return true;
}
bool operator<=(const String& s)
{
char* str1 = (_str + 4);
char* str2 = (_str + 4);
while (*str1&&*str2)
{
if (*str1<*str2)
return true;
else if (*str1>*str2)
return false;
else
{
str1++;
str2++;
}
}
if (*str1 == *str2)
return true;
else
return false;
}
bool operator>(const string& s)
{
char* str1 = (_str + 4);
char* str2 = (_str + 4);
while (*str1&&*str2)
{
if (*str1>*str2)
return true;
else if (*str1<*str2)
return false;
else
{
str1++;
str2++;
}
}
if (*str1 == '/0')
return false;
else
return true;
}
bool operator>=(const String& s)
{
char* str1 = (_str + 4);
char* str2 = (_str + 4);
while (*str1&&*str2)
{
if (*str1>*str2)
return true;
else if (*str1<*str2)
return false;
else
{
str1++;
str2++;
}
}
if (*str1 == *str2)
return true;
else
return false;
}
bool operator==(const String& s)
{
char* str1 = (_str + 4);
char* str2 = (_str + 4);
while (*str1++ == *str2++)
{
if (*(--str1) == '/0')
return true;
}
return false;
}
bool operator!=(const String& s)
{
return !(operator==(s));
}
char* C_str()
{
Checkreallocate();
return (_str + 4);
}
void Print()
{
cout << (_str + 4) << endl;
}
private:
char* _str;
size_t _size;
size_t _capacity;
};