当一个类中没有指针类型的成员变量时,是不会发生浅拷贝的问题的
但是如果存在的话,就会引发浅拷贝问题
我们来举个例子
class CString
{
public:
CString(const *str = NULL);//普通构造函数
CString(const CString &other);//拷贝构造函数
CStirng & operator = (const CString &other);//赋值重载函数
~CString();//析构函数
private:
char * m_data;
};
/
这是CString类的一些函数,它含有指针,所以必须自定义拷贝构造函数和赋值函数
首先,我们要知道这么一点:就是在C++中,编译器会有自己默认的拷贝构造函数和赋值函数(当我们自己不定义的时候)
但是在它调用自己默认的拷贝构造函数或者赋值函数的时候会发生浅拷贝问题(当有指针成员变量的时候)
浅拷贝会造成什么问题呢????????????
看图我i们就很清楚了
对象1 对象2
对象2浅拷贝了一份对象1中的m_data
它们同时指向同一块堆内存,当两个对象析构的时候,这块堆内存就会被析构两次,编译肯定会出错
解决方法:就是对象2必须申请属于自己的堆空间
再看看默认赋值运算函数会造成什么问题 ????????????????????
对象1 对象2
其实和上面的问题差不多,也会发生同一块堆内存被释放两次,而且因为赋值运算的前提是两个对象必须都是存在的才能进行赋值
所以如果对象1要赋值给对象2,对象2原来的数据还没有被释放,还会发生内存泄漏的问题。
解决方法:
必须先释放它原先有的东西,再申请空间,再进行拷贝,这样才不会出错
//
代码实现
#include <iostream>
using namespace std;
class CString
{
public:
CString(const char *str = NULL)//普通构造函数
{
if(str == NULL)
{
m_data = new char[1];
}
else
{
m_data = new char[strlen(str)+1];
strcpy(m_data,str);
}
}
CString(const CString &other)//自定义拷贝构造函数
{
m_data = new char[strlen(other.m_data)+1];//申请空间
strcpy(m_data,other.m_data);//再进行拷贝
}
CString & operator = (const CString &other)//自定义赋值函数
{
if(this == &other)
{
return *this;//防止自己给自己赋值,返回对象
}
delete []m_data;//删除原有数据
m_data = new char[strlen(other.m_data)+1];//申请空间
strcpy(m_data,other.m_data);//进行拷贝
return *this;//为了实现连续赋值
}
~CString()//析构函数
{
delete []m_data;//释放堆内存
m_data = NULL;//指针置空,防止野指针
}
void show()
{
cout<<m_data<<endl;
}
private:
char *m_data;
};
int main()
{
CString str1("lalalalalala");
CString str2("hahahahahaha");
CString str3(str1);
str3.show();
str1 = str2;
str1.show();
}
如果我们不自己写拷贝构造函数和赋值函数呢?????????????
class CString
{
public:
CString(const char *str = NULL)//普通构造函数
{
if(str == NULL)
{
m_data = new char[1];
}
else
{
m_data = new char[strlen(str)+1];
strcpy(m_data,str);
}
}
~CString()//析构函数
{
delete []m_data;//释放堆内存
m_data = NULL;//指针置空,防止野指针
}
void show()
{
cout<<m_data<<endl;
}
private:
char *m_data;
};
int main()
{
CString str1("lalalalalala");
CString str2("hahahahahaha");
CString str3(str1);
str3.show();
str1 = str2;
str1.show();
}
/所以当我们以后类中有指针类型的成员变量时,一定要自定义拷贝构造函数和赋值函数/