一种通过创建临时空间解决写时拷贝问题的方法
指路:模拟实现string类。地址:https://blog.csdn.net/MPF1230/article/details/104059562
源代码获取:
https://github.com/akh5/C-/blob/master/STL/copyOnWrite.cpp
由于浅拷贝多个对象共用一个资源,导致其中一个对象修改其内容时,会导致其他对象也会进行相应修改。
如果当前s1对象将 s1[0] 元素改为“A”,则s2,s3的0号元素也将改为"A"
为了解决这种问题,我们需要新建一个临时资源,将s1指向一个临时资源,在临时资源内修改,s1就与s2,s3独立开来。
namespace my
{
class string
{
public:
string(char* str = "")
:_pCount(new int(1))
{
if (nullptr == str)
str = "";
//申请空间
_str = new char[strlen(str) + 1]; //“\0”
strcpy(_str, str);
}
//浅拷贝
string(const string& s)
:_str(s._str)
, _pCount(s._pCount)
{
++*_pCount;
}
string &operator=(const string& s)
{
if (this != &s)
{
//需要将当前对象的旧资源释放掉
if (0 == --*_pCount)
{
delete[] _str;
delete _pCount;
}
_str = s._str;
_pCount = s._pCount;
(*_pCount)++;
}
return *this;
}
~string()
{
if (_str && --*_pCount == 0)
{
delete[] _str;
_str = nullptr;
delete _pCount;
_pCount = nullptr;
}
}
char& operator[](size_t index)
{
if (GetRef() > 1)
{
string strtemp(_str);
this->swap(strtemp);
}
return _str[index];
}
void swap(string& s)
{
std::swap(_str, s._str);
std::swap(_pCount, s._pCount);
}
private:
int GetRef()
{
return *_pCount;
}
char* _str;
int* _pCount;
};
}
关于解决写实拷贝问题,集中体现在[]运算符的重载函数中
char& operator[](size_t index)
{
if (GetRef() > 1)
{
string strtemp(_str);
this->swap(strtemp);
}
return _str[index];
}
先判断当前资源的引用量是否大于1,大于1时说明已经有多个对象使用当前资源,所以调用自身的拷贝构造,构造一个临时的作用域strtemp,并使用this指针将两者内容交换,一旦出了if函数的作用域,strtemp会自动调用析构函数,销毁自己,并将资源计数器减1。
一开始,s1,s2,s3的地址都是相同的,
对s1[0]进行修改,s1的指针与临时空间交换,所以s1的地址与s2,s3不同,s1修改了A,s2,s3与先前一样