浅拷贝问题
当用一个类对象去初始化这个类的另一个对象时,如果这个类没有提供拷贝构造函数以及重载=运算符,这时就会发生浅拷贝。如下代码所示
class Name
{
public:
Name(const char *pname)
{
this->size=strlen(pname);
this->pName=(char *)malloc(size+1);
strcpy(this->pName,pname);
}
~Name()
{
if(pName!=NULL)
{
free(pName);
pNmae=NULL;
size=0;
}
}
private:
char *pName;
int size;
}
void fun1()
{
Name obj1("obj1");//初始化obj1
Name obj2 = obj1;//用obj1去初始化obj2,这种情况会发生浅拷贝
}
void fun2()
{
Name obj3("obj3");
obj3=obj1;//将obj1赋值给obj1 这种情况会发生浅拷贝
}
int main()
{
fun1();
fun2();
return 0;
}
上述代码的内存图如图所示
-
由此可知,在类中含有指针时,如果没有定义拷贝构造函数,系统会默认地对指针进行浅拷贝,即系统默认的拷贝构造函数并不会为 obj2 的pName指针申请新的内存空间,而是直接将指针指向obj1 的pName的内存空间。
这样就会带来严重的问题:当obj2被析构时,obj2 pName所指向的内存空间就会被释放掉,当析构obj1 pName所指向的内存空间时,发现内存空间早已被obj2的指针给释放掉,这时就会引发系统崩溃。 -
如果未重载=运算符,obj3=obj1 也会引发类似的问题
浅拷贝解决方法
· 深拷贝
为了防止由浅拷贝所带来的同一内存空间的多次释放,需要重新定义拷贝构造函数以及重载=操作符,为新对象初始化及进行赋值操作时额外申请内存空间,进行深拷贝。
代码如下所示
class Name
{
public:
Name(const char *pname)
{
this->size=strlen(pname);
this->pName=(char *)malloc(size+1);
strcpy(this->pName,pname);
}
Name(Name &obj)//定义拷贝构造函数
{
this->size=obj.size;
this->pName=(char *)malloc(size+1);
strcpy(this->pName,obj.pName);
}
//重载=操作符
Name& operator=(Name &obj)
{
if(pName!=NULL)
{
free(pName);
pName=NULL;
size=0;
}
this->size=obj.size;
this->pName=(char *)malloc(size+1);
strcpy(this->pName,obj.pName);
return *this;
}
~Name()
{
if(pName!=NULL)
{
free(pName);
pNmae=NULL;
size=0;
}
}
private:
char *pName;
int size;
}
内存图为
有了各自的内存空后,就不会出现同一内存空间被释放两次的情况
结论
当类中有指针成员时,需要注意指针的内存空间的使用情况,避免发生浅拷贝,必要时进行深拷贝。