浅拷贝:
多个对象共用同一块内存空间,在析构时会出现问题。
例如:创建了三个String类对象
String s1="hello";
String s2(s1);
String s3;
s3=s2;
s2创建时调用拷贝构造函数,使得s2的指针指和s1的指向都为“hello”这块空间。
s3创建时调赋值运算符的重载,使得s1,s2,s3都指向同一空间,则在析构时会出现问题。并且会导致s3的内存泄漏问题。
浅拷贝代码:
#include<iostream>
using namespace std;
# pragma warning (disable:4996)
class String
{
public:
String(const 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) //拷贝构造函数
:_pStr(s._pStr)
{}
String& operator=(const String& s) //赋值运算符重载函数
{
if (this != &s)
{
_pStr = s._pStr;
}
return *this;
}
~String() //析构函数
{
if (_pStr)
{
delete[] _pStr;
_pStr = NULL;
}
}
private:
char* _pStr;
};
int main()
{
String s1 = "hello";
String s2(s1); //调用构造函数
String s3;
s3 = s2; //调用赋值运算符重载函数
return 0;
}
深拷贝:
为每个对象都分配内存空间,防止析构时出现错误。
深拷贝代码如下:
#include<iostream>
using namespace std;
# pragma warning (disable:4996)
class String
{
public:
String(const 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) //拷贝构造函数
:_pStr(new char[strlen(s._pStr)+1])
{}
String& operator=(const String& s) // 赋值运算符重载函数
{
if (this != &s)
{ //为防止申请空间失败导致的原空间内存丢失,用临时变量保存
char* pTemp = new char[strlen(s._pStr) + 1];
strcpy(pTemp, s._pStr);
delete[] _pStr;
_pStr = pTemp;
}
return *this;
}
~String() //析构函数
{
if (_pStr)
{
delete[] _pStr;
_pStr = NULL;
}
}
private:
char* _pStr;
};
int main()
{
String s1 = "hello";
String s2(s1);
String s3;
s3 = s2;
system("pause");
return 0;
}
总结:深浅拷贝的主要区别在于是否共用空间。两者的代码只有拷贝构造函数和赋值运算符重载时,深拷贝需要重新开辟空间,而浅拷贝仅仅改变了指针的指向。