浅拷贝
先来看一段代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <string.h>
using namespace std;
class String
{
public:
//构造函数
String(const char *_pstr = "")
:m_iSize(strlen(_pstr)+1)
{
m_pstr = new char[m_iSize];
m_pstr[m_iSize] = '\0';
}
//拷贝构造函数
String(const String& _string)
:m_iSize(_string.m_iSize)
{
if (this != &_string)
{
m_pstr = _string.m_pstr;
}
}
~String()
{
if (NULL != m_pstr)
{
delete[] m_pstr;
m_pstr = NULL;
}
}
private:
char* m_pstr;
int m_iSize;
};
void Funtest()
{
String s1("hello world");
String s2(s1);
}
int main()
{
Funtest();
return 0;
}
String s1(“hello world”);
调用String类的构造函数,将形参的内容拷贝到m_pstr中。
String s2(s1);
调用String类的拷贝构造函数,让m_pstr指向形参m_pstr空间。
接着函数向下执行,先析构s2,将s2.m_pstr所指向的空间释放,接下来释放s1,s1一直指向所申请空间,m_pstr已经为空,又去调析构函数去释放,程序崩溃。
注意:
当类里面有只针对象的时候,拷贝构造和赋值运算符重载值进行值拷贝(浅拷贝),两个对象同时指向同一块内存,对象销毁时该空间被释放了2次,程序崩溃。
深拷贝
简单的来说,【浅拷贝】是增加了一个指针,指向原来已经存在的内存。而【深拷贝】是增加了一个指针,并新开辟了一块空间,让指针指向这块新开辟的空间。
这里写了3个版本
1.普通版2.简洁版3.引用计数
//深拷贝---普通版
class String
{
friend ostream& operator<<(ostream& _cout, String& s);
public:
String(const char* pStr = "")
{
if (NULL == pStr)
{
char* pTemp = new char[1];
_pStr = pTemp;
*_pStr = '\0';
}
else
{
char* pTemp = new char[strlen(pStr) + 1];
_pStr = pTemp;
strcpy(_pStr, pStr);
}
}
~String()
{
if (NULL != _pStr)
{
delete[] _pStr;
_pStr = NULL;
}
}
String(const String& s)
{
char* pTemp = new char[strlen(s._pStr) + 1];
strcpy(pTemp, s._pStr);
_pStr = pTemp;
}
String& operator=(const String& s)
{
if (this != &s)
{
char* pTemp = new char[strlen(s._pStr) + 1];
strcpy(pTemp, s._pStr);
_pStr = pTemp;
}
return *this;
}
String& operator+(const String& s)
{
char* _pCutStr = _pStr;
char* _pSCurStr = s._pStr;
char* Temp = new char[my_strlen(_pCutStr) + my_strlen(_pSCurStr) + 1];
my_strcpy(Temp, _pCutStr);
my_strcat(Temp, _pSCurStr);
_pStr = Temp;
return *this;
}
//String& operator+(const String& s, size_t pos, size_t n);
bool operator>(const String& s)
{
if (this->Compare(s) > 0)
return true;
else
return false;
}
bool operator<(const String& s)
{
if (this->Compare(s) < 0)
return true;
else
return false;
}
bool operator==(const String& s)
{
if (this->Compare(s) == 0)
return true;
else
return false;
}
String Copy(const String& s)
{
char* _pTstr = _pStr;
char* sor = s._pStr;
while (*_pTstr++ = *sor++)
{
}
return *this;
}
String Copy(const String& s, size_t n)
{
char* _pTstr = _pStr;
char* sor = s._pStr;
while ((n--) && (*_pTstr++ = *sor++))
{
}
return *this;
}
String StrStr(const String& s)
{
String cp;
cp._pStr = (char *)_pStr;
String s1, s2;
if (!*s._pStr)
return((char *)_pStr);
while (*cp._pStr)
{
s1._pStr = cp._pStr;
s2._pStr = (char *)s._pStr;
while (*s1._pStr && *s2._pStr && !(*s1._pStr - *s2._pStr))
{
s1._pStr++;
s2._pStr++;
}
if (!*s2._pStr)
return(cp._pStr);
cp._pStr++;
}
return(NULL);
}
private:
int Compare(const String& s)
{
char* src = _pStr;
char*dst = s._pStr;
int ret = 0;
while (!(ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
{
++src;
++dst;
}
if (ret < 0)
ret = -1;
else if (ret > 0)
ret = 1;
return(ret);
}
int my_strlen(char* _pStr)
{
char* _pTstr = _pStr;
int lenth = 0;
while (*_pTstr++)
{
++lenth;
}
return lenth;
}
char* my_strcpy(char* dec,const char* sor)
{
char* _pTstr = dec;
while (*_pTstr++ = *sor++)
{}
return _pTstr;
}
char* my_strcat(char* dec, const char* sor)
{
char* _pTstr = dec;
while (*_pTstr)
{
_pTstr++;
}
while (*_pTstr++ = *sor++)
{
;
}
return _pTstr;
}
private:
char* _pStr;
};
ostream& operator<<(ostream& _cout, String& s)
{
_cout << s._pStr;
return _cout;
}
void FunTest()
{
String str1 = "hello world";
String str2 = "delete";
bool ret = str1 > str2;
String str3;
cout << str1.StrStr(str2) << endl;
}
深拷贝——简洁版
class String
{
public:
String(const char* pStr = "")
{
if (NULL == pStr)
{
char* pTemp = new char[1];
_pStr = pTemp;
*_pStr = '\0';
}
else
{
char* pTemp = new char[strlen(pStr) + 1];
_pStr = pTemp;
strcpy(_pStr, pStr);
}
}
~String()
{
if (NULL != _pStr)
{
delete[] _pStr;
_pStr = NULL;
}
}
String(const String& s)
{
String pTemp(s._pStr);
_pStr = NULL;
std::swap(_pStr, pTemp._pStr);
}
String& operator=(const String& s)
{
if (this != &s)
{
String pTemp(s._pStr);
std::swap(_pStr, pTemp._pStr);
}
return *this;
}
private:
char* _pStr;
};
void FunTest()
{
String str1 = "hello";
String str2 = str1;
String str3="word";
String str4=str3;
str3 = str2;
}
浅拷贝优化-引用计数
class String
{
public:
friend ostream& operator<<(ostream& _cout, String& s);
String(const char* pStr = "")
{
if (NULL == pStr)
{
char* pTemp = new char[1];
_pStr = pTemp;
*_pStr = '\0';
}
else
{
char* pTemp = new char[strlen(pStr) + 1 + 4];
*(int*)pTemp = 1;
_pStr = (char*)((int*)pTemp + 1);
strcpy(_pStr, pStr);
}
}
~String()
{
char* temp = (char*)((int*)_pStr - 1);
if (--*(int*)temp == 0)
{
delete[] temp;
_pStr = NULL;
}
}
String(const String& s)
{
char* temp = (char*)((int*)s._pStr - 1);
*(int*)temp += 1;
_pStr = s._pStr;
}
String& operator=(const String& s)
{
if (this != &s)
{
char* temp = (char*)((int*)_pStr - 1);
if (--*(int*)temp == 0)
{
delete[] temp;
_pStr = NULL;
}
_pStr = s._pStr;
*((int*)_pStr - 1) += 1;
}
return *this;
}
private:
char* _pStr;
};
ostream& operator<<(ostream& _cout, String& s)
{
_cout << s._pStr;
return _cout;
}
void FunTest()
{
String s1;
String s2 = "hello";
String s3 ="word";
/*String s4 = s3;*/
s3 = s2;
cout << s3 << endl;
/*cout << s4 << endl;*/
}
int main()
{
FunTest();
system("pause");
return 0;
}
写时拷贝
顾名思义,写时拷贝就是在需要修改这块空间的内容时才分配一块空间。同样用上边的例子,写时拷贝会存在一个计数器,并且多个对象指向同一块空间,每次创建一个新的对象时,计数器++,销毁时计数器 - -
写时拷贝
class String
{
public:
friend ostream& operator<<(ostream& _cout, String& s);
String(const char* str = "")
{
if (NULL == str)
{
char* pTemp = new char[1];
*pTemp = '\0';
_pStr = pTemp;
int* pCTemp = new int(1);
_pCount = pCTemp;
}
else
{
char* pTemp = new char[strlen(str) + 1];
strcpy(pTemp, str);
_pStr = pTemp;
int* pCTemp = new int(1);
_pCount = pCTemp;
}
}
~String()
{
if (--(*_pCount) == 0)
{
delete[] _pStr;
_pStr = NULL;
delete _pCount;
_pCount = NULL;
}
}
String(const String& str)
{
_pStr = str._pStr;
_pCount = str._pCount;
(*_pCount)++;
}
String& operator=(const String& str)
{
if (this != &str)
{
if (--(*_pCount) == 0)
{
delete[] _pStr;
_pStr = NULL;
delete _pCount;
_pCount = NULL;
}
_pStr = str._pStr;
_pCount = str._pCount;
(*_pCount)++;
}
return *this;
}
private:
char* _pStr;
int* _pCount;
};
ostream& operator<<(ostream& _cout, String& s)
{
_cout << s._pStr;
return _cout;
}
void FunTest()
{
String s1 = "hello";
cout << s1 << endl;
String s2 = s1;
cout << s2 << endl;
String s3 = "word";
s3 = s2;
}