堆与拷贝构造函数ppt培训课件

上传人:aa****6 文档编号:54512609 上传时间:2018-09-14 格式:PPT 页数:32 大小:76KB
返回 下载 相关 举报
堆与拷贝构造函数ppt培训课件_第1页
第1页 / 共32页
堆与拷贝构造函数ppt培训课件_第2页
第2页 / 共32页
堆与拷贝构造函数ppt培训课件_第3页
第3页 / 共32页
堆与拷贝构造函数ppt培训课件_第4页
第4页 / 共32页
堆与拷贝构造函数ppt培训课件_第5页
第5页 / 共32页
点击查看更多>>
资源描述

《堆与拷贝构造函数ppt培训课件》由会员分享,可在线阅读,更多相关《堆与拷贝构造函数ppt培训课件(32页珍藏版)》请在金锄头文库上搜索。

1、C + 程序设计教程(修订版),第十四章 堆与拷贝构造函数,清华大学出版社 钱 能,第十四章 堆与拷贝构造函数,关于堆 需要new和delete的原因 分配堆对象 拷贝构造函数 默认拷贝构造函数 浅拷贝与深拷贝 临时对象 无名对象 构造函数用于类型转换,1、关于堆,全局变量、静态数据、常量存放在全局数据区,所有类成员函数和非成员函数代码存放在代码区,为运行函数而分配的局部变量、函数参数、返回数据、返回地址等存放在栈区,余 下的空间都被作为堆区。 堆内碎块:堆区内众多不连续的内存小块动态分配内存应注意:及时释放内存,避免堆区碎块,2、需要new和delete的原因,在C+用new代替malloc

2、()函数的一个原因是,它在分配空间的时候不能调用构造函数。类对象的建立是分配空间、构造结构以及初始化的三位一体,他们统一由构造函数来完成。例如,下面的代码用malloc()分配对象空间:class Tdate public:Tdate();SetDate(int m=1,int d=1,int y=1998);,protected:int month;int day;int year;Tdate:Tdate()month=1;,2、需要new和delete的原因,day=1;year=1;void Tdate:SetDate(int m,int d,int y)if(m0 ,2、需要new和d

3、elete的原因,void fn()Tdate * pD; /仅仅是个指针,没有产生对象pD=(Tdate*)malloc(sizeof Tdate); /并不调用构造函数/free(pD); /并不调用析构函数此时pD是一个含有类对象空间,对应的对象空间中的值不确定。为此,内存分配之后再进行初始化。,2、需要new和delete的原因,例如,下面的代码描述用malloc()来进行对象的创建过程:void fn()Tdate * pD;pD=(Tdate*)malloc(sizeof Tdate);pD-SetDate(); /设置Tdate值/free(pD);从根本上说,不是类对象的创建,

4、因为它绕过了构造函数。,2、需要new和delete的原因,3 分配堆对象,堆对象的作用域:文件 用new分配的对象,在用delete释放前,一直占有堆空间,不管能否访问得到。堆对象创建时(new)自动调用构造函数,释放时(delete)自动调用析构函数分配堆对象: 形式1:指针标识符 = new 类型标识符; 形式2:指针标识符 = new 类型标识符(初始化值); 形式3:指针标识符 = new 类型标识符数组维数; /对于数组,不能初始化释放堆对象: 形式1:delete 指针标识符; 形式2:delete指针标识符;/释放堆数组,3 分配堆对象,看一下下面代码与前面的代码做一比较:vo

5、id fn()Tdate * pS;pS=new Tdate; /分配堆空间并构造它/delete pS; /先析构,然后将空间返还给堆构造函数可以有参数,所以跟在new后面的类类型也可以跟参数。例如下面的代码,new后面的类型必须跟参数:,3 分配堆对象,class Tdatepublic:Tdate(int m,int d,int y);protected:int month;int day;int year;Tdate:Tdate(int m,int d,int y),if(m0,3 分配堆对象,/delete(pD);“pD=new Tdate(1,1,1998);”这一名,使new去

6、调用了构造函数Tdate(int,int,int),new是根据参数匹配的原则来调用构造函数的。如果上一句写成:pD=new Tdate; 则由于Tdate类没有默认构造函数而使该语句报错。 从堆中还可以分配对象数组。例如,下面的代码分配了参数给定的对象个数,并在函数结束时,予以返还:,3 分配堆对象,class Studentpublic:Student(char * pName=“no name”)strncpy(name,pName,sizeof(name);namesizeof(name)-1=“0”;protected:char name40;,3 分配堆对象,void fn(int

7、 noOfObjects)Student * pS=new StudentnoOfObjects;/delete pS;分配过程将激发noOfObjects次构造函数的调用,从 0noOfObjects-1。调用构造函数的顺序依次为pS0,pS1,psnoOfObjects-1。由于分配数组时,new的格式是类型后面跟元素个数,不能再跟构造函数参数。如果该类没有默认构造函数,则不能分配对象数组。,3 分配堆对象,4、拷贝构造函数,拷贝构造函数:特殊的构造函数 作用:当用一个已存在的对象构造一个新的对象时,系统不自动调用构造函数、而是自动调用拷贝构造函数;创建新的对象,并把对象的数据成员值拷贝给

8、新的对象(在编译时进行)。拷贝构造函数声明的一般形式:类名(const 类名&形参对象名);拷贝构造函数定义的一般形式:类名:类名(const 类名&形参对象名) ,4、拷贝构造函数,拷贝构造函数被调用的3种情况:1.新建对象:class A;void main() A a;A a1(a);2.实参传递给形参时:void f(A a) void main() A a;f(a);3.函数返回时:A fn() A a; return a;void main() f(fn(); ,4、拷贝构造函数,可用一个对象去构造另一个对象,或者说,用另一个对象值初始化一个新构造的对象,例如:Student s1

9、(“Jenny”);Student s2=s1;/用s1的值去初始化s2对象作为函数参数传递时,也要涉及对象的拷贝,例如:void fn(Student fs)/,void main()Student ms;fn(ms);函数fn()的参数传递的方式是传值,参数类型是Student,调用时,实参ms传给了形参fs,ms在传递的过程中是不会改变的,形参fs是ms的一个拷贝,形参fs用ms的值进行构造。这时候,调用构造函数Student(char *)就不合适,新的构造函数的参数应是Student,4、拷贝构造函数,4、拷贝构造函数,#include #include class Student

10、public:Student(char* pName=“no name“,int ssId=0)strncpy(name,pName,40);name39=0;id = ssId;cout “Constructing new student “ pName endl;Student(Student& s) /拷贝构造函数,cout “Constructing copy of “ s.name endl; strcpy(name,“copy of “);strcat(name,s.name);id=s.id;Student()cout “Destructing “ name endl;prote

11、cted:char name40;int id; ;,4、拷贝构造函数,void fn(Student s)cout “In function fn()n“;void main()Student randy(“Randy“,1234);cout “Calling fn()n“;fn(randy);cout “Returned from fn()n“;,4、拷贝构造函数,5、默认拷贝构造函数,如果不定义拷贝构造函数,系统自动为类提供一个缺省的拷贝构造函数(逐一拷贝数据成员)。 一般情况下,不必定义拷贝构造函数。但是,如果构造函数中存在动态分配,则必须定义拷贝构造函数 例:#include#inc

12、ludeclass A private: int *p;public: A(int i) p=new int(i); cout“new.“endl; A() cout“delete p.“endl; delete p; ;int main() A a1(5); /调用构造函数A a2(a1); /调用系统提供的缺省的拷贝构造函数return 0; /*调用析构函数两次,一个值为5的int型对象被删除两次,在运行时会产生问题*/*执行结果:new.delete p. delete p. 执行到此,出错:指针p已经被释放 */,/定义拷贝构造函数来解决上述问题#include#includecla

13、ss A private: int *p;public: A(int i)p=new int(i);cout“new.“endl;A(const A/*执行结果:new.copy_constructor.delete p.delete p. */,5、默认拷贝构造函数,6、浅拷贝与深拷贝,在默认拷贝构造函数中,拷贝的策略是逐个成员依次拷贝。但是,一个类可能会拥有资源,当其构造函数分配了一个资源的时候,会发生什么呢?如果拷贝构造函数简单地制作了一个该资源的拷贝,而不对它本身分配,就面临一个麻烦的局面:两个对象都拥有同一个资源。当对象析构时,该资源将经历两次资源返还。,调用默认拷贝构造函数,使得p

14、2与p1完全一样,并没有新分配堆空间给p2,见下图:,6、浅拷贝与深拷贝,创建p2时,对象p1被复制给了p2,但资源并未复制,因此,p1和p2指向同一个资源,这称为浅拷贝。当一个对象创建时,分配了资源,这时,就需要定义自己的拷贝构造函数,使之不但拷贝成员,也拷贝资源。,6、浅拷贝与深拷贝,拷贝构造函数中,不但复制了对象空间,也复制资源,见下图:,6、浅拷贝与深拷贝,创建p2时,对象p1被复制给了p2,同时资源也作了复制,因此,p1和p2指向不同的资源,这称为深拷贝。如果你的类需要析构函数来析构资源,则它也需要一个拷贝构造函数。因为通常对象是自动被析构的。如果需要一个自定义的析构函数,那就意味着

15、有额外资源要在对象被析构之前释放。此时,对象的拷贝就不是浅拷贝了。,6、浅拷贝与深拷贝,7、临时对象,当函数返回一个对象时,要创建一个临时对象来存放返回的对象 Student fn() /. student ms(“Randy“); return ms; int main() student s; s=fn(); ,ms,临时对象,S,8、无名对象,class Student /. Student(char *) ; fn() Student(“Rand“);/此处为无名对象 无名对象:实际存在、但没有标识符的对象,9、构造函数用于类型转换,class Student public: Student(char *); /. ; void fn(Student /等价于 fn(Student(“Jenny“) ,

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > PPT模板库 > PPT素材/模板

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号