浅拷贝:也称位拷贝,编译器只是直接将指针的值拷贝过来,当多个对象共用同一块内存,当一 个对象将这块内存释放掉之后,另一些对象不知道该块空间已经还给了系统,以为还有效,所以 在对这段内存进行操作的时候,发生了访问违规。
代码实现浅拷贝:
引用计数—-普通版
/*给引用计数也创建一个内存空间,并且和共享内存一样,让引用计数也共享*/
class String
{
public:
String(const char* str = "")
:_pCount(new int(1))
{
if (NULL == str)
{
_str = new char[1];
*_str = '\0';
}
else
{
_str = new char[strlen(str) + 1];
strcpy(_str, str);
}
}
String(const String& s)
:_str(s._str)
,_pCount(s._pCount)
{
++(*_pCount);
}
String& operator=(const String& s)
{
if (_str!=s._str)
{
if (_str && 0 == --(*_pCount))
{
delete[] _str;
delete _pCount;
}
_str = s._str;
_pCount = s._pCount;
++(*_pCount);
}
return *this;
}
~String()
{
if (_str&&0 == --(*_pCount))
{
delete[] _str;
_str = NULL;
delete _pCount;
_pCount = NULL;
}
}
void Print()
{
cout << _str << endl;
}
private:
char* _str;
int* _pCount;
friend ostream& operator <<(ostream&cout, const String& s);
};
ostream& operator <<(ostream& cout, const String& s)
{
cout << s._str;
return cout;
}
void FunTest()
{
String s1("Hello World");
String s2(s1);
String s3("Hello");
String s4(s3);
s2 = s3;
s4 = s1;
s1.Print();
s2.Print();
s3.Print();
s4.Print();
}
int main()
{
FunTest();
return 0;
}
引用计数——-精简版
class String
{
public:
String(const char* str = "")
{
if (NULL == str)
{
_str = new char[1+4];
_str += 4;
*_str = '\0';
}
else
{
_str = new char[strlen(str) + 1+4];
_str += 4;
strcpy(_str, str);
}
GetRef() = 1;
}
String(const String& s)
:_str(s._str)
{
++GetRef();
}
String& operator=(const String& s)
{
if (_str != s._str)
{
Release();
_str = s._str;
++GetRef();
}
return *this;
}
~String()
{
Release();
}
void Print()
{
cout << _str << endl;
}
void Release()
{
if (_str && 0 == --GetRef())
{
_str -= 4;
delete[] _str;
_str = NULL;
}
}
protected:
int& GetRef()//获取引用计数
{
return *((int*)_str - 1);
}
private:
char* _str;
friend ostream& operator <<(ostream&cout, const String& s);
};
ostream& operator <<(ostream& cout, const String& s)
{
cout << s._str;
return cout;
}
void FunTest()
{
String s1("Hello World");
String s2(s1);
String s3("Hello");
String s4(s3);
s2 = s3;
s4 = s1;
s1.Print();
s2.Print();
s3.Print();
s4.Print();
}
int main()
{
FunTest();
return 0;
}
深拷贝:编译器将一个对象的内容全部拷贝到另外一个对象中,两个对象各自独立管理一块空间,当释放时,各自调用析构函数,别的空间不受影响。
深拷贝—-普通版
class String
{
public:
String(const char* str = "")
{
if (NULL == str)
{
_str = new char[1];
*_str = '\0';
}
else
{
_str = new char[strlen(str) + 1];
strcpy(_str, str);
}
}
String(const String& s)
:_str(new char[strlen(s._str)+1])
{
strcpy(_str, s._str);
}
String& operator=(const String& s)
{
if (this != &s)
{
//方法一 开辟空间失败对原没存不存在影响
//char* temp = new char[strlen(s._str)+1];//申请新空间
//strcpy(temp, s._str); //拷贝元素
//delete[] _str; //释放就空间
//_str = temp; //使用新空间
//方法二 开辟空间失败对原空间存在影响 原空间的内容被释放
delete[] _str; //释放旧空间
_str = new char[strlen(s._str) + 1]; //申请新空间
strcpy(_str, s._str); //使用新空间 拷贝元素
}
return *this;
}
~String()
{
if (_str)
{
delete[] _str;
_str = NULL;
}
}
void Print()
{
cout << _str<private:
char* _str;
friend ostream& operator <<(ostream&cout, const String& s);
};
ostream& operator <<(ostream& cout, const String& s)
{
cout << s._str;
return cout;
}
int main()
{
String s1 = "Hello World!";
String s2("Hello Bit!");
String s3(s2);
String s4;
s4 = s1;
s1.Print();
s2.Print();
s3.Print();
s4.Print();
return 0;
}
深拷贝——–简洁版
class String
{
public:
String(const char* str = "")
{
if (NULL == str)
{
_str = new char[1];
*_str = '\0';
}
else
{
_str = new char[strlen(str) + 1];
strcpy(_str, str);
}
}
String(const String& s)
:_str(NULL)//如果不初始化,那么_str就是一个野指针,指向的空间是随机值,再次使用会造成内存访问冲突
{
String strTemp(s._str);
swap(_str, strTemp._str);
}
//方法一
String& operator=(const String& s)
{
if (this != &s)
{
String strTemp(s);
swap(_str, strTemp._str);
}
return *this;
}
//方法二
/*String& operator=(const String& s)
{
String strTemp(s);
swap(_str, strTemp._str);
return *this;
}*/
//方法三
/*String& operator=(String s)
{
swap(_str, s._str);
return *this;
}*/
~String()
{
if (_str)
{
delete[] _str;
_str = NULL;
}
}
void Print()
{
cout << _str << endl;
}
private:
char* _str;
friend ostream& operator <<(ostream&cout, const String& s);
};
ostream& operator <<(ostream& cout, const String& s)
{
cout << s._str;
return cout;
}
int main()
{
String s1 = "Hello World!";
String s2("Hello Bit!");
String s3(s2);
String s4;
s4 = s1;
s1.Print();
s2.Print();
s3.Print();
s4.Print();
return 0;
}