浅拷贝:也称位拷贝,编译器只是直接将指针的值拷贝过来,结果多个对象共用同一块内存,当一个对象将这块内存释放掉之后,另一些对象不知道该块空间已经还给了系统,以为还有效,所以在对这段内存进行操作的时候,发生了访问违规。
深拷贝:为避免浅拷贝的问题,存在内存拷贝时开辟一块和被拷贝对象一样大小的空间并将其内存中的数据也拷贝到新开辟的内存中
一、普通深拷贝
#include <iostream>
using namespace std;
class String
{
public:
String(char* ptr = ""): //构造函数
_pStr(new char[strlen(ptr) + 1])
{
strcpy(_pStr, ptr);
}
String(const String& s): //拷贝构造
_pStr(new char[strlen(s._pStr) + 1])
{
strcpy(_pStr, s._pStr);
}
String& operator= (const String& s)//赋值运算符重载
{
if (this != &s)
{
if(_pStr)
delete[] _pStr;
_pStr = new char[strlen(s._pStr) + 1];
strcpy(_pStr, s._pStr);
}
return *this;
}
~String()
{
if (_pStr)
{
delete[] _pStr;
_pStr = NULL;
}
}
private:
char* _pStr;
};
int main()
{
String s;
String s1("hello");
String s2(s1);
s = s2;
system("pause");
return 0;
}
二、简单深拷贝
#include <iostream>
using namespace std;
class String
{
public:
String(char* ptr = "") : //构造函数
_pStr(new char[strlen(ptr) + 1])
{
strcpy(_pStr, ptr);
}
String(const String& s) : //拷贝构造
_pStr(NULL)
{
String temp(s._pStr);
swap(temp._pStr, _pStr);
}
String& operator=(const String& s) //赋值运算符重载
{
if (this != &s)
{
String temp(s);
swap(temp._pStr, _pStr);
}
return *this;
}
~String() //析构函数
{
if (_pStr)
{
delete[] _pStr;
}
}
size_t Size()const // 获取大小
{
return (Lengh()*sizeof(char) + 1);
}
size_t Lengh()const //获取长度
{
size_t length = 0;
char* p = _pStr;
while (*p++)
{
length++;
}
return length;
}
char& operator[](size_t index) //随机访问
{
return *(_pStr + index);
}
const char& operator[](size_t index)const
{
return *(_pStr + index);
}
bool operator>(const String& s) //大于运算符重载
{
char* s1 = _pStr;
char* s2 = s._pStr;
while (*s1 == *s2 && *s2)
{
++s1;
++s2;
}
if ((*s1 - *s2) > 0)
{
return 1;
}
else
{
return 0;
}
}
bool operator<(const String& s) //小于运算符重载
{
if (*this > s)
{
return 0;
}
else
{
return 1;
}
}
bool operator==(const String& s) //等于运算符重载
{
char* s1 = _pStr;
char* s2 = s._pStr;
while (*s1 == *s2 && *s2)
{
++s1;
++s2;
}
if ((*s1 - *s2) == 0)
{
return 1;
}
else
{
return 0;
}
}
bool operator!=(const String& s) //不等于运算符重载
{
if (*this == s)
{
return 0;
}
else
{
return 1;
}
}
void Copy(const String& s) //拷贝函数
{
char* dest = _pStr;
char* src = s._pStr;
if (s.Lengh() < Lengh())
{
while (*dest++ = *src++)
{
;
}
}
else
{
delete[] _pStr;
_pStr = new char[s.Lengh() + 1];
while (*dest++ = *src++)
{
;
}
}
}
bool strstr(const String& s) //找子串
{
char* dest = _pStr;
char* src = s._pStr;
char* cur = _pStr;
while (*cur++)
{
dest = cur;
src = s._pStr;
while (*dest == *src && *src)
{
++src;
++dest;
}
if ( *src == '\0' )
{
return 1;
}
}
return 0;
}
String& operator+=(const String& s) //+=符号重载
{
char* temp = new char[Lengh() + s.Lengh() + 1];
strcpy(temp, _pStr);
delete[] _pStr;
_pStr = temp;
char* dest = _pStr;
char* src = s._pStr;
while (*dest)
{
++dest;
}
while (*dest++ = *src++)
{
;
}
return *this;
}
private:
char* _pStr;
};
int main()
{
String s("helloworld");
String s1("hello");
String s2(s1);
String s3("world");
size_t a = s1.Size();
size_t b = s1.Lengh();
s1 += s3;
s2.Copy(s1);
bool x = (s == s1);
system("pause");
return 0;
}
三、引用计数 (多开辟一块空间,用来存放对象使用同一块空间的个数)
#include <iostream>
#include <assert.h>
using namespace std;
class String
{
public:
String(char* ptr = "") :
_pStr(new char[strlen(ptr) + 1 + 4]) //多开辟4个字节
{
_pStr += 4;
strcpy(_pStr, ptr);
Count() = 1;
}
String(const String& s):
_pStr(s._pStr)
{
Count()++;
}
String& operator=(const String& s)
{
if (this != &s)
{
Release();
_pStr = s._pStr;
Count()++;
}
return *this;
}
~String()
{
if (_pStr && (0 == --Count()))
{
delete[] (_pStr - 4);
}
}
char& operator[](size_t num)
{
assert( num < strlen(_pStr));
return *(_pStr + num);
}
private:
void Release()
{
if (0 == --Count())
{
delete[] (_pStr - 4);
}
}
int& Count()
{
_count = (int *)(_pStr - 4);
return (*_count);
}
char* _pStr;
int* _count; //计数
};
int main()
{
String s;
String s1("hello");
String s2(s1);
String s3(s);
s = s2;
s1[0] = 'a';
system("pause");
return 0;
}