第7章 关于函数的高级专题.ppt

  1. 1、本文档共28页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
第7章 关于函数的高级专题 合理使用函数能将程序模块化,大大降低了问题的规模,提高了编码效率,方便以后复用代码。函数的参数传递有传值,传指针和传引用3种方式,从类型的角度上看,参数不仅仅可以是系统内建的数据类型,还可以是数组、结构以及后面要介绍的类对象等等,同时,内存使用注意事项、函数与指针的关系也是学习C++必须迈过的槛。 7.1 内存使用错误剖析 编写代码时,少不了和内存打交道,很多程序员对此提心吊胆,称内存为“雷区”或“bug集中营”似乎并不过份。即使是久经沙场的老手,有时也难免落入内存错误的陷阱。本节帮助读者了解这些常见的错误,在编程时加以注意,把出错的概率降到最低。 7.1.1 内存泄露 使用new或malloc()动态申请的内存,如果不再使用,应该把它释放掉,为程序节省内存空间,方便后面的使用。在C/C++中,内存管理器不会自动回收不再使用的内存。如果忘记释放不再使用的内存,在程序的运行过程中,这些内存就不能再被使用用,就造成了所谓的“内存泄露”。 内存泄露是最为常见的错误,现在的计算机配置比较高,内存容量很大,一两处内存泄露通常不至于让程序崩溃,也不会出现逻辑上的错误,进程退出时,系统会自动释放该进程所有相关的内存,所以内存泄露的后果相对来说并不是灾害性的。但这并不意味着完全没有危险,如果程序规模较大、长时间运行,或者是内存资源相对紧张的场合,内存泄露过多会导致内存耗尽,系统没有后继内存可以使用,程序可能会崩溃。 第6章讲过,代码块中声明的局部变量在代码块执行完毕后会自动消亡,那如果是在代码块中申请的动态内存,系统会自动回收么,答案是否定的,如: if ( condition ) { int* p = new int[8]; } 7.1.2 野指针 前面提到“指针消亡,并不意味着其指向的内存会被自动释放”,同样“释放动态内存,并不意味着指针会消亡,也不意味着指针的值会改变”,如: int* p=new int[8]; …… delete[] p; 指向完delete[] p后,指针p是不是就自动消亡了呢,错,不论是使用delete/delete[]还是使用free(),指针p非但不会消亡,其值也保持不变,并不会变为null。这时,使用“if (p!=null)”进行处理也无法起到防错作用。 为此,指针被free或delete/delete[]后,一定要置为null,没有置为null的指针常称为“野指针”,释放掉的堆内存会被内存管理器重新分配,野指针指向的内存已经被赋予新的意义。如果使用野指针释放或再次访问这块内存,会给程序带来灾难性的后果。 7.1.3 试图修改常量 程序中出现的字符串常量和其他全局常量(如全局const常量),是存放在.rodata里面的,.rodata内存页面是不能修改的,试图对常量修改,会引发内存错误,如代码7?2 。 7.1.4 用错sizeof 运算符sizeof()可以计算数组的大小(字节数),但对指针来说,sizeof仅仅得到指针变量的字节数。但当数组作为函数的参数进行传递时,数组退化为同类型的指针,用sizeof是无法取得数组的大小的。 代码7?3演示了sizeof的用法: 7.1.5 内存越界访问 使用指针和数组访问某块内存区域时,编译器并不会对数组下标是否越界、指针是否有效进行检查,如果不注意,很容易造成内存越界访问的错误,内存越界访问有两种:一种是读越界,一种是写越界,常称作缓冲区溢出。 读越界,即读了不属于自己的数据,如果所读的内存地址是无效的,程序会立刻崩溃,但如果所读内存地址是有效的,在读的时候不会出问题,但读到的数据是随机的,会产生不可预料的后果。 写越界,即往不该写的内存地址空间中写了东西,这往往会给程序带来很多匪夷所思的错误和BUG,有些症状是随机的,时有时无,给问题分析带来很多的困难。 一些辅助工具可以帮忙检查内存越界,但从根本上说,在编程时应十分小心,特别是对于外部传入的参数要仔细检查,另外,要做好程序的防错处理。 7.1.6 变量的初始化 不论是指针变量,还是普通变量,一定要时刻牢记“初始化”,虽然编译器会对有的变量自动初始化为0,但在声明变量时就对它进行初始化,是一个编程的好习惯,还要重视编译器的警告信息,发现有引用未初始化的变量,立即修改过来。 7.2 重申:函数参数传递和返回机制 前面已经提及,函数的参数传递有值传递、指针传递和引用传递,函数返回也可是返回值、返回指针或返回引用。抛开引用传递,对值和指针,不论是参数传递还是函数返回,理解“副本”的概念十分重要。 7.2.1 参数传递时的“副本” 先来看一下函数调用的过程,不论是值传递还是指针传递,编译器都要为每个函数制作临时副本,函数体中对参数的修改都是对副本的修改,对传值调用来说

文档评论(0)

yyh892289 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档