更多点子:c++—目录索引(知识小渠道)
String:浅拷贝之引用计数+写时拷贝
浅拷贝:当类里面有指针对象时,进行简单赋值的浅拷贝,两个对象指向同一块内存,析构时delete两次这块内存,存在崩溃问题,这时得进行深拷贝
深拷贝:(String s2=s1)构造s2时拷贝一块跟s1指向数据块一样大的数据块,并将值拷贝下来,这样s1和s2指向各自的数据块,析构时delete各自的数据块
写时拷贝还是建立在浅拷贝上的,新变量和原来的共用一块数据,引用计数+1,如果谁需要变化,就重新开辟一块空间,把数据给考过来,然后在上面修改怎么样的,如果没有修改的就不用再开辟空间,只是将计数器+1,赚到
引用计数+写时拷贝
_PCount(计数器是成员变量)
namespace COW//copy on write
{
class String
{
public:
String(const char* str = "")
:_str(new char[strlen(str) + 1])
, _pCount(new int(1))
{
strcpy(_str, str);
}
String( const String& s)
:_str(s._str)
, _pCount(s._pCount)
{
(*_pCount)++;
}
//s1= s3
String& operator=(const String& s)
{
if (&s != this)
{
/*if (--(*_pCount) == 0)
{
delete[] _str;
delete _pCount;
}*/
Release();
_str = s._str;
_pCount = s._pCount;
++(*_pCount);
}
return *this;
}
void CopyOnWrite()//凡是可能会写(改变)的接口,就调这个函数
{
if (*_pCount > 1)//说明这段空间不是一个人独占的,那我就得重新弄一个
{
char* newstr = new char[strlen(_str) + 1];
strcpy(newstr, _str);
_str = newstr;
--(*_pCount);
_pCount = new int(1);//新开辟出来的空间,引用计数为1
}
}
/*void Insert(size_t pos, const char* str)
{
CopyOnWrite();
...
}*/
char& operator[](size_t pos)//读的时候也可能会修改,不如调CopyOnWrite先期完成
{
CopyOnWrite();
return _str[pos];
}
const char& operator[](size_t pos)const
{
return _str[pos];
}
const char* c_str()
{
return _str;
}
void Release()//并不是真的释放,是检查引用计数
{
if (--(*_pCount) == 0)
{
delete[] _str;
delete _pCount;
_str = NULL;
_pCount = NULL;
}
}
~String()
{
Release();
}
private:
char* _str;
int* _pCount;
};
}
引用计数+写时拷贝
计数器在字符串开头前4个字节
class String
{
public:
String(const char* str = "")
:_str(new char[strlen(str)+5])
{
_str += 4;
strcpy(_str, str);
//*((int*)(_str - 4)) = 1;
GetRefCount() = 1;
}
//s2(s1)
String(const String& s)
:_str(s._str)
{
++GetRefCount();
}
//s1=s2
String& operator=(const String& s)
{
if (this != &s)
{
this->Release();
_str = s._str;
++GetRefCount();
}
return *this;
}
int& GetRefCount()
{
return *((int*)(_str - 4));
}
void Release()
{
if (--GetRefCount() == 0)
{
delete[](_str - 4);
}
}
void CopyOnWrite()
{
if (GetRefCount() > 1)
{
char* newstr = new char[strlen(_str) + 5];
newstr += 4;
strcpy(newstr, _str);
--GetRefCount();//这儿指的是原来的计数
_str = newstr;
GetRefCount() = 1;//这儿是后来新的计数
}
}
char& operator[](size_t pos)
{
CopyOnWrite();
return _str[pos];
}
~String()
{
Release();
}
private:
char* _str;
};
如果有什么不对的地方,可以评论告诉我,望指导!