浅拷贝定义:
浅拷贝,指的是在对象复制时,只是对对象中的数据成员进行简单的复制,默认拷贝构造函数执行的也是浅拷贝。简单的说,浅拷贝就是值传递,将源空间里面的内容复制到目标空间中。
缺陷:多个指针可能共用管理一块内存空间,在释放时,导致对一块空间的多次释放,造成内存泄露。
深拷贝定义:
在“深拷贝”的情况下,对于对象中动态成员,就不能仅仅简单地赋值了,而应该重新动态分配空间。
浅拷贝实现
include<iostream>
using namespace std;
class String
{
public :
String(const char*pStr="")
{
if(NULL==pStr)
{
_pStr=new char[1];
*_pStr='\0';
}
else
{
_pStr=new char[strlen(pStr)+1];
strcpy(_pStr,pStr);
}
}
String(const String& s)
:_pStr(s._pStr)
{
}
String& operator=(const String& s)
{
if(this!=&s)
{
_pStr=s._pStr;
}
return *this;
}
~String ()
{
if(_pStr)
{
delete[] _pStr;
_pStr=NULL;
}
}
private:
char* _pStr;
};
void FunTest()
{
String s1("hello");
String s2(s1);
String s3;
s3=s1;
}
int main ()
{
FunTest();
String s1("hello");
String s2(s1);
String s3(NULL);
String s4(s1);
s3=s4;
s3=s1;
return 0;
}
完成深拷贝
引入引用计数:指示当前空间有多少指针指向该空间.
注意:用计数可以普通的成员变量,引用计数不可以为普通的成员变量,因为一旦出了作用域,该空间被销毁,达不到想要的效果.因此可以采用private类型的static型变量.
#include<iostream>
using namespace std;
class String
{
public :
String(const char* pStr="")
:_pCount(new int (1))
{
if(NULL==pStr)
{
_pStr=new char[1];
*_pStr='\0';
}
else
{
_pStr=new char[strlen(pStr)+1];
strcpy(_pStr,pStr);
}
}
String (const String& s)
:_pStr(s._pStr)
,_pCount(s._pCount)
{
++(*_pCount);
}
String& operator=(const String& s)
{
if(_pStr!=s._pStr)
{
if(_pStr&&0==--*_pCount)
{
delete [] _pStr;
delete _pCount;
}
_pStr =s._pStr;
_pCount=s._pCount;
++_pCount;
}
return *this;
}
~String ()
{
if(_pStr&&(0==--*_pCount))
{
delete[] _pStr;
_pStr=NULL;
delete _pCount;
_pCount=NULL;
}
}
private:
char* _pStr;
int* _pCount;
};
void FunTest()
{
String s1("hello");
String s2(s1);
String s3;
s3=s2;
}
int main()
{
FunTest();
return 0;
}
写时拷贝
写时拷贝:如果要朝当前对象写东西,建议使用这种方式,且单线程不会有问题
#include<iostream>
using namespace std;
class String
{
public :
String(const char* pStr="")
{
if(NULL==pStr)
{
_pStr=new char[1+4];
_pStr+=4;
*_pStr='\0';
}
else
{
_pStr=new char[strlen(pStr)+1+4];
_pStr+=4;
strcpy(_pStr,pStr);
}
GetRaf()=1;
}
String (const String& s)
:_pStr(s._pStr)
{
GetRaf()++;
}
String& operator=(const String& s)
{
if(_pStr!=s._pStr)
{
Release();
_pStr =s._pStr;
++GetRaf();
}
return *this;
}
~String ()
{
Release();
}
char& operator [] (size_t index)
{
if(GetRaf()>1)
{
char* pTemp=new char [strlen(_pStr)+1+4];
*(int*)pTemp=1;
pTemp+=4;
strcpy(pTemp,_pStr);
--GetRaf();
_pStr=pTemp;
}
return _pStr[index];
}
const char& operator [](size_t index)const
{
return _pStr[index];
}
private:
int& GetRaf()
{
return *((int*)_pStr-1);
}
void Release()
{
if(_pStr&&(0==--GetRaf()))
{
_pStr-=4;
delete[] _pStr;
_pStr=NULL;
}
}
private:
char* _pStr;
};
void FunTest()
{
String s1("hello");
String s2(s1);
s2[0]='w';
String s3;
s3=s2;
}
int main()
{
FunTest();
return 0;
}