String类与深浅拷贝

时间:2022-07-20 19:49:47

浅拷贝

1、概念:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅拷贝仅仅复制所考虑的对象,而不是复制它所引用的对象。 2、举例
class String
{
public:
String(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)
{
strcpy(_pStr,s._pStr);
}

String& operator = (const String& s)
{
if (_pStr != s._pStr)
{
_pStr = s._pStr;
}
return *this;
}

~String()
{
if (NULL != _pStr)
{
delete[] _pStr;
_pStr = NULL;
}
}
private:
char* _pStr;
};
void FunTest()
{
String s0;
String s1 = ("hello");
String s2(s1);
String s3 = s1;
}
int main()
{
FunTest();
return 0;
}

////////////浅拷贝优化一不能实现所有的拷贝///////////////

class String
{
public:
String(char* pStr = "")//构造函数浅拷贝
:_pCount(1)
{
if (NULL == pStr)
{
_pStr = new char[1];
*_pStr = '\0';
}
else
{
_pStr = new char[strlen(pStr)+1];
strcpy(_pStr,pStr);
}
}

String(String& s)//拷贝构造函数
:_pStr(s._pStr)//当前指针和s指针指向同一个空间
,_pCount(++s._pCount)
{}

String& operator = (String& s)//赋值运算符重载
{
if (_pStr != s._pStr)//判断是否自我赋值
{
if (0 == --_pCount)//判断当前指向this指针所指空对象的个数是否为0,如果为0就释放该空间
{
delete[]_pStr;
}
_pCount = ++s._pCount;//如果不为0指向新空间,则指向该空间对象数加1
_pStr = s._pStr;
}
return *this;
}

~String()//析构函数
{
if (0 == _pCount)
{
delete[] _pStr;
_pStr = NULL;
}
}
private:
char* _pStr;
int _pCount;
};
void FunTest()
{
String s1 = ("hello");
String s2(s1);//拷贝构造
String s3;
s3 = s1;//赋值重载
}
int main()
{
FunTest();
return 0;
}

////////////////////浅拷贝优化二可以实现部分拷贝////////////////////////////

class String
{
public:
String(char* pStr = "")//构造函数浅拷贝
{
if (NULL == pStr)
{
_pStr = new char[1];
*_pStr = '\0';
}
else
{
_pStr = new char[strlen(pStr)+1];
strcpy(_pStr,pStr);
}
_pCount = 1;
}

String(String& s)//拷贝构造函数
:_pStr(s._pStr)//当前指针和s指针指向同一个空间
{
++_pCount;
}

String& operator = (String& s)//赋值运算符重载
{
if (_pStr != s._pStr)//判断是否自我赋值
{
if (0 == --_pCount)//判断当前指向this指针所指空对象的个数是否为0,如果为0就释放该空间
{
delete[]_pStr;
}
++_pCount;//如果不为0指向新空间,则指向该空间对象数加1
_pStr = s._pStr;
}
return *this;
}

~String()//析构函数
{
if (0 == _pCount)
{
delete[] _pStr;
_pStr = NULL;
}
}
private:
char* _pStr;
static int _pCount;//类里声明
};

int String::_pCount = 0;//类外定义


void FunTest()
{
String s1 = ("hello");
String s2(s1);//拷贝构造


String s3(s1);
s3 = s1;//赋值重载


//////////////static不能处理下面这种//////////////
//String s1 = ("hello");
//String s2(s1);
//String s4("world");
//String s5(s4);
//s5 = s2;
}
int main()
{
FunTest();
return 0;
}


/////////////////浅拷贝3所有类型可以全部实现////////////////////////////////

class String
{
public:
String(char* pStr = "")//构造函数浅拷贝
:_pCount(new int(1))//开辟计数空间赋值为1
{
if (NULL == pStr)
{
_pStr = new char[1];
*_pStr = '\0';
}
else
{
_pStr = new char[strlen(pStr)+1];
strcpy(_pStr,pStr);
}
}

String(String& s)//拷贝构造函数
:_pStr(s._pStr)//当前指针和s指针指向同一个空间
,_pCount(s._pCount)//两个对象指向同一个计数空间
{
++(*_pCount);//多了一个对象加1
}

String& operator = (String& s)//赋值运算符重载
{
if (_pStr != s._pStr)//判断是否自我赋值
{
if (0 == --(*_pCount))//当前对象引用计数加1,如果为0就释放该空间
{
delete[]_pStr;
delete _pCount;

}
_pStr = s._pStr;
_pCount = s._pCount;//指向新的对象引用计数
++(*_pCount);//如果不为0新空间引用计数加1
}
return *this;
}

~String()//析构函数
{
if (0 == (*_pCount))
{
delete[] _pStr;
delete _pCount;
_pStr = NULL;
_pCount = NULL;
}
}
private:
char* _pStr;
int* _pCount;
};

void FunTest()
{
String s1 = ("hello");
String s2(s1);//拷贝构造


String s3(s1);
s3 = s1;//赋值重载

String s4("world");
String s5(s4);
s5 = s2;
}
int main()
{
FunTest();
return 0;
}

深拷贝

1、概念:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量,那些引用其他对象的变量将指向被复制的对象,而不是原来有那些引用的对象,换言之,深复制把要复制的对象所引用的对象都复制一遍2、举例
/////////////深拷贝普通版///////////////////////
class String
{
public:
String(char* pStr = "")//构造函数的构造函数
{
if (NULL == pStr)//判断是否为空,若为空,开辟一个大小为1的空间
{
_pStr = new char[1];
*_pStr = '\0';
}
else
{
_pStr = new char[strlen(pStr)+1];
strcpy(_pStr,pStr);
}
}
String(const String& s)//深拷贝拷贝构造函数
:_pStr(new char[strlen(s._pStr)+1])//初始化列表给_pStr开辟新空间,防止后面析构函数释放该空间出错。
{
strcpy(_pStr,s._pStr);
}

String& operator = (const String &s)//深拷贝赋值运算符重载
{
if (this != &s)//判断是否自己给自己赋值
{
///////////////////////////////////////////////////////////////////////////////////////////////

//delete[]_pStr;//释放当前this指针所指的空间
//_pStr = new char [strlen(s._pStr)+1];
//strcpy(_pStr,s._pStr);

///////////////////上面的方法存在问题,如果新开辟空间失败,原this指针所指的就发生改变///////////

char *pTmp = new char[strlen(s._pStr)+1];//创建临时指针变量,指向新开辟的地址
strcpy(pTmp,s._pStr);//s里的值拷贝到临时指针变量所指的空间
delete[]_pStr;//释放当前this指针所指的空间
_pStr = pTmp;//当前this指针指向临时变量所指的空间
}
return *this;
}

~String()//深拷贝析构函数
{
if (NULL != _pStr)
{
delete[] _pStr;
_pStr = NULL;
}
}
private:
char * _pStr;
};
void FunTest()
{
String s1 = ("hello");
String s2(s1);
String s3 = s1;
}
int main()
{
FunTest();
return 0;
}

///////////////////深拷贝简洁版/////////////////////////////
class String
{
public:
String(const char* pStr = "")//深拷贝构造函数
{
if (NULL == pStr)//判断是否为空,若为空,开辟一个大小为1的空间
{
_pStr = new char[1];
*_pStr = '\0';
}
else
{
_pStr = new char[strlen(pStr) + 1];
strcpy(_pStr, pStr);//交换指针
}
}
String(const String& s)//深拷贝拷贝构造函数
:_pStr(NULL)//初始化列表给_pStr指向空,防止后面析构函数释放该空间出错。
{
String str(s._pStr);//创建临时对象和当前string内容相同
std::swap(_pStr, str._pStr);//当前this指针和临时对象的指针交换
}

String& operator = (const String& s)//赋值运算符重载<1>
{
if (this != &s)//判断是否自我交换
{
String str(s);//调拷贝构造函数
std::swap(_pStr, str._pStr);//交换指针所指的空间
}
return *this;
}

String& operator = (String s)//赋值运算符重载<2>,值的形式传递,创建临时变量
{
std::swap(_pStr, s._pStr);
return *this;
}

~String()//深拷贝的析构函数
{
if (NULL != _pStr)
{
delete[] _pStr;
_pStr = NULL;
}
}
private:
char* _pStr;
};

void FunTest()
{
string s1("hello");
string s2(s1);
string s3;
s3 = s2;
}
int main()
{
FunTest();
system("pause");
return 0;
}