笔记四十九:C+中的浅拷贝

看程序:

#define_CRT_SECURE_NO_WARNINGS

#include

usingnamespacestd;

className

{

public:

//构造函数

Name(constchar*myp)

{

len=strlen(myp);//字符串的长度,不含'0'

p=(char*)malloc(len+1);//申请内存,要包含0

strcpy (p,myp);//字符串放到类中

}

//析构函数

~Name()

{

if(p!=NULL)

{

free(p);

p=NULL;

len=0;

}

}

protected:

private:

char*p;

intlen;

};

voidobjplay()

{

Name obj1("abcdefg");

Name obj2=obj1;//调用obj2的拷贝构造函数

//没写拷贝构造函数,使用C++编译器默认的拷贝构造函数

//C++编译器提供的拷贝构造函数是一个浅拷贝

//就是指针变量赋值了,但是指针变量所指向的内存空间没有被拷贝过去

}

intmain()

{

objplay();

system("pause");

return0;

}

我们运行上面的程序,发现运行出错:

我们分析一下:Name obj1("abcdefg");这个语句我们定义一个类的对象,此时会调用构造函数,在构造函数中申请一块内存,用于存放字符串。

接下来Name obj2=obj1;定义一个对象obj2,因为没有拷贝构造函数,因此会调用默认的拷贝构造函数,这个构造函数是一个浅拷贝。就是指针变量赋值了,指针变量指向的内存空间没有拷贝过去。

解释一下浅拷贝:

简单的说,在有指针的情况下,浅拷贝只是增加了一个指针指向已经存在的内存。(而深拷贝是增加一个指针并且申请一个新的内存,使这个增加的指针指向这个新的内存,采用深拷贝的情况下,释放内存的时候就不会出现浅拷贝时重复释放同一内存的错误。)

我们来分析一下为什么会运行出错!

先来看对象obj1,对象有两个属性,指针p和存放字符串长度的len,执行语句Name obj1("abcdefg");时会调用构造函数,在构造函数中将字符串的长度7赋给len,因此len变量的内存中就是7,然后申请内存,指针p指向这块内存,然后将字符串投放到申请的内存中。

然后执行Name obj2=obj1;会调用默认的拷贝构造函数,但这个默认的拷贝构造函数是一个浅拷贝,就是说,把对象obj1的两个属性,拷贝一份然后给obj2,是把指针变量的值拷贝了,但是没有把指针变量指向的内存内容也拷贝一份,也就是两个指针指向同一块内存。

然后函数执行完后我们会调用析构函数,先构造的后析构,因此先析构obj2对象,会调用析构函数,会把刚刚申请的内存空间给析构释放,然后p变成NULL,len变成0。

但是obj2的属性跟obj1的属性是没有关系的,obj2析构了,但是obj1还在,obj1中的指针p还指向一个已经释放的内存,也就成了野指针,接下来析构obj1对象会调用obj1的析构函数,又会执行一次析构,因为之前申请的内存空间已经析构了,所以再析构,析构两次同一块内存空间,就会出错。

下一个笔记,也就是笔记五十,说一下用深拷贝解决上面这个问题。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180424A0KI1U00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码关注腾讯云开发者

领取腾讯云代金券