写时拷贝copy_on_write的方式实现基本的String类,从字面意思来讲就是在需要修改字符串的时候将其拷贝一份,然后进行修改。这里引入了引用计数的概念,在写时拷贝时我们需要注意以下几个问题:
1.开始开辟空间时会多开辟4个字节,是引用计数存放的空间,数据从4个字节以后开始存放;
2.在进行重新写入时,如果引用计数为1那么只需要修改即可,不用再进行拷贝;如果引用计数大于1,在修改时才需要重新拷贝一份;
3.再释放空间时,千万要记得连引用计数那块4个字节的空间一起delete.
下面给出用写时拷贝的方式实现基本String类的代码:
#include<iostream>
#include<cstring>
#include<assert.h>
using namespace std;
class String
{
friend ostream& operator<<(ostream& os,const String& s);
public:
String(const char* str=""):_str(new char[strlen(str)+1+4])
{
_str=_str+4; //找到数据存放的地方(数组前面4个字节是引用计数的空间)
GetCount()=1;
strcpy(_str,str);
}
String(const String& s):_str(s._str)
{
++GetCount();
}
~String()
{
if(--GetCount()==0)
{
delete[] (_str-4); //连存放引用计数那块空间一起释放
}
}
String& operator=(String& s)
{
if(this!=&s)
{
if(--GetCount()==0)
{
delete[] (_str-4);
}
++s.GetCount();
_str=s._str;
}
return *this;
}
char& operator[](int index)
{
assert(index>=0); //表达式为真,继续执行下面的
assert(index<(int)strlen(_str));
if(GetCount()>1)
{
--GetCount();
char* tmp=new char[strlen(_str)+1+4]; //tmp临时变量,出作用域自行销毁
strcpy(tmp+4,_str);
_str=tmp+4;
GetCount()=1;
}
return _str[index];
}
private:
char* _str;
int& GetCount() //引用计数
{
return *((int*)_str-1);
}
};
ostream& operator<<(ostream& os,const String& s)
{
os<<s._str<<endl;
return os;
}
void test1()
{
String s1("hello world");
String s2(s1);
String s3;
s3=s1;
cout<<s1<<endl;
cout<<s2<<endl;
cout<<s3<<endl;
}
void test2()
{
String s1("work");
s1[3]='d';
cout<<s1<<endl;
}
int main()
{
test2();
system("pause");
return 0;
}