浅拷贝:只是对指针的拷贝,拷贝后两个指针指向同一块内存空间,两个对象共享一份资源,当一个对象销毁时就会将资源释放 掉,而另一个对象不知道资源已经释放,以为还有效,所以继续对资源进行访问时就会发生访问违规。
#include<iostream>
#include<assert.h>
#include<unistd.h>
#include<string.h>
#include<unistd.h>
using namespace std;
class String
{
public:
String(const char* str = "")
{
// 构造string类对象时,如果传递NULL指针,认为程序非法,此处断言下
if(NULL == str)
{
assert(false);
return;
}
_str = new char[strlen(str) + 1];
strcpy(_str, str);
}
~String()
{
if(_str)
{
delete[] _str;
_str = NULL;
}
}
private:
char* _str;
};
// 测试
void TestString()
{
String s1("hello bit!!!");
String s2(s1);
}
int main()
{
TestString();
return 0;
}
深拷贝:不仅对指针进行拷贝,对指针指向的内容也进行拷贝,深拷贝后的指针指向两个不同地址。这样释放内存的时候就不会
出现同一块空间多次释放的问题。
传统写法:
#include<unistd.h>
#include<string.h>
#include<assert.h>
using namespace std;
class String
{
public:
String(const char* str="")
{
if(NULL==str)
{
assert(false);
return;
}
_ret=new char[strlen(str)+1];
strcpy(_ret,str);
}
String(const String& s)
:_ret(new char[strlen(s._ret)+1])
{
strcpy(_ret,s._ret);
}
String& operator=(const String& x)
{
if(this!=&x)
{
delete[] _ret;
char* tmp=new char[strlen(x._ret)+1];
strcpy(tmp,x._ret);
_ret=tmp;
}
return *this;
}
~String()
{
if(_ret)
{
delete[] _ret;
_ret=NULL;
}
}
private:
char* _ret;
};
int main()
{
String s1("haha");
String s2(s1);
return 0;
}
现代方法:
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<string>
using namespace std;
class String
{
public:
String(const char* tmp="")
{
if(tmp==NULL)
{
assert(false);
return;
}
_ret=new char[strlen(tmp)+1];
strcpy(_ret,tmp);
}
String(const String& s)
:_ret(new char[strlen(s._ret)+1])
{
strcpy(_ret,s._ret);
}
/*
String& operator=(String& x)
{
swap(_ret,x._ret);
return *this;
}*/
String& operator=(const String& x)
{
if(this!=&x)
{
String strtmp(x);
swap(_ret,strtmp._ret);
}
return *this;
}
~String()
{
if(_ret)
{
delete[] _ret;
_ret=NULL;
}
}
private:
char* _ret;
};
int main()
{
String s1("haha");
String s2(s1);
return 0;
}