为什么要用写时拷贝?
在c++中一个类有六个默认成员函数,其中拷贝构造函数分为浅拷贝和深拷贝;
浅拷贝是一种值拷贝,深拷贝不仅是值拷贝,还要做其他处理;
深浅拷贝的区别:
由上图可知当一个拷贝构造一个需动态开辟空间的对象时,用浅拷贝时会出现同一块空间被释放两次,这样显然有问题,用深拷贝的话可以解决此问题,但当拷贝构造出来的对象,不需要修改时,使用深拷贝就有些浪费空间了,采用引用计数的写时拷贝能更好的解决问题。
如何实现写时拷贝?
写时拷贝,按其意思来说就是在“写”(修改)的时候进行拷贝,它要实现的是既不浪费空间,又不使同一空块空间析构多次;因此它才用引用计数的方法来实现写时拷贝;(以string类为例)
具体代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include
using namespace std;
class String
{
public:
String(const char *str="")
:_str(new char[strlen(str)+1])
,_refcount(NULL)
{
strcpy(_str,str);
_refcount=new int(1);
}
String(const String& s)
:_str(s._str)
,_refcount(NULL)
{
_refcount=s._refcount;
(*_refcount)++;
}
String& operator=(const String& s)
{
if(_str!=s._str)
{
Release();
_str=s._str;
_refcount=s._refcount;
++(*_refcount);
}
return *this;
}
~String()
{
Release();
}
public:
void CopyOnWrite()
{
if(*_refcount>1)
{
char *tmp=new char[strlen(_str)+1];
strcpy(tmp,_str);
--(*_refcount);
_str=tmp;
_recount=new int(1);
}
}
void Release()
{
if(--(*_refcount)==0)
{
delete[] _str;
delete _refcount;
}
}
private:
char *_str;
int *_refcount;
};
int main()
{
String s1("hello");
String s2(s1);
s2=s1;
return 0;
}
以上这种方法,创建对象时需要都需给_refcount创建新的空间,释放的时候也需释放两次,效率比较低,那能不能进行改进呢?
原理图:
具体代码:
#define _CRT_SECURE_NO_WARNINGS 1
//引用计数的写时拷贝(浅拷贝)
#include
using namespace std;
class String
{
public:
String(const char *str="")
:_str(new char[strlen(str)+5])
{
_str+=4;
strcpy(_str,str);
(*(int *)(_str-4))=1;
}
String(const String& s)
:_str(s._str)
{
GetRefcount()++;
}
~String()
{
Release();
}
String& operator=(const String& s)
{
if(_str!=s._str)
{
if(--GetRefcount()==0)
{
Release();
}
_str=s._str ;
GetRefcount()++;
}
}
void Release()
{
if(GetRefcount()==1)
{
delete[] (_str-4);
cout<<"delect"<
1)
{
char* tmp=new char[strlen(_str)+5];
tmp+=4;
strcpy(tmp,_str);
_str=tmp;
GetRefcount()=1;
}
}
public :
int& GetRefcount()
{
return (*(int *)(_str-4));
}
char* GetStr()
{
return _str;
}
char& operator[](size_t pos)
{
CopyOnWrite();
return _str[pos];
}
private:
char *_str;
};
int main()
{
String s1("hello");
String s2(s1);
String s3=s2;
s3[1]='m';
cout<
<