版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
指
针
指针与内存指针如何创建动态内存。指针如何释放所创建的动态内存野指针的处理办法。熟练的掌握指针如何创建动态内存和释放所创建的动态内存,熟练的掌握野指针的处理办法。1在C++程序中,一些变量在整个程序中都是可见的,称为全局变量。一些只能在一个函数中可知,称为局部变量。1.6.9指针与程序内存2一个程序将操作系统分配给其运行的内存块分为4个区域:1)代码区,存放系统的代码,即程序中的各个函数代码块。2)全局数据区,存放程序的全局数据和静态数据。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。在C/C++程序中,不管是局部变量,全局变量、或是动态变量,在内存中都占用一定的空间,但是它们占用不同的空间。1.6.9指针与程序内存33)堆区,存放程序的动态数据。程序在运行的时候用new申请任意多的内存,程序员自己负责在何时用delete释放内存。4)栈区,存放程序的局部数据,即各个函数中的数据。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。1.6.9指针与程序内存4在C++中,申请和释放堆中分配的存贮空间,分别使用new和delete的两个运算符来完成:申请内存使用new:例如:1、int*pi=newint(0);
它与下列代码序列大体等价:
2、intival=0,*pi=&ival;区别:pi所指向的变量是由库操作符new()分配的,位于程序的堆区中,并且该对象未命名。指针变量名=new类型名(初始化式);1.6.10指针与动态内存5new运算符返回的是一个指向所分配类型变量(对象)的指针。对所创建的变量或对象,都是通过该指针来间接操作的,而动态创建的对象本身没有名字。例如以下代码:int*pi=newint(12);其中pi为这个指针的名称,而12这个整型并没对象,pi保存了12所在的内存的内存地址。1.6.10指针与动态内存6在堆中建立动态一维数组原型如下:注意:“下标表达式”不是常量表达式,即它的值不必在编译时确定,可以在运行时确定。指针变量名=new类型名[下标表达式];例如以下代码:intival=10;int*pi=newint[ival];1.6.10指针与动态内存7在代码栏编写以下代码,编译并查看输出:#include<iostream>usingnamespacestd;voidmain(){intn;char*pc;cout<<"请输入动态数组的元素个数"<<endl;cin>>n;pc=newchar[n];strcpy(pc,"veryGood");cout<<pc<<endl;delete[]pc;system(“pause”);}1.6.10指针与动态内存8在堆中释放指针所创建的内存原型如下:堆空间申请、释放演示:⑴.用初始化式(initializer)来显式初始化int*pi=newint(0);⑵.当pi生命周期结束时,必须释放pi所指向的目标:deletepi;delete指针变量名;注意这时释放了pi所指的目标的内存空间,也就是撤销了该目标,称动态内存释放(dynamicmemorydeallocation),但指针pi本身并没有撤销,它自己仍然存在,该指针所占内存空间并未释放,需要注意的是任何类型指针的都会占用四个字节的内存。1.6.10指针与动态内存9特别需要注意的是,如果该指针又指向了别处,那么在释放以前务必要保证指针从新指回原来的内存地址:例如以下代码,运行时程序会奔溃:#include<iostream>usingnamespacestd;voidmain(){ int*pi=newint(9); intival=5; pi=&ival; deletepi; system(“pause”);}1.6.10指针与动态内存10在堆中释放指针所创建的数组内存原型如下:注意:方括号非常重要的,如果delete语句中少了方括号,因编译器认为该指针是指向数组第一个元素的,会产生回收不彻底的问题(只回收了第一个元素所占空间),加了方括号后就转化为指向数组的指针,回收整个数组。delete[]的方括号中不需要填数组元素数,系统自知。即使写了,编译器也忽略。delete[]指向该数组的指针变量名1.6.10指针与动态内存11如果指向数组的指针移动了,或者指向了别的内存地址,那么在释放前务必要将该指针回归原位,最快捷的办法是做原始内存地址的备份。例如以下代码,演示了如何做原始内存地址的备份:#include<iostream>usingnamespacestd;voidmain(){ int*pi=newint[10]; int*temp=pi; intival=20; pi=&ival; pi=temp; delete[]pi; system(“pause”);}1.6.10指针与动态内存12编译器不能自动发现内存错误,通常是在程序运行时才能捕捉到。常见的内存错误及对策:1)内存分配未成功,却使用了它。int*pB;*pB=10;解决办法:在使用内存之前检查指针是否为NULL。assert(p!=NULL)if(p==NULL)或if(p!=NULL)1.6.10指针与动态内存132)内存分配虽然成功,但是尚未初始化就引用它。解决办法:无论用何种方式创建数组,都别忘了赋初值,即便是赋零值也不可省略。例如以下代码:#include<iostream>usingnamespacestd;voidmain(){ int*pi=newint[10]; for(inti=0;i<10;i++) cout<<pi[i]<<endl; system(“pause”);}1.6.10指针与动态内存143)内存分配成功并且已经初始化,但操作越过了内存的边界。charstrText[8];sprintf(strText,"Thisisalongtext!");解决办法:留心数组的大小,避免数组操作越界。1.6.10指针与动态内存155)释放了内存却继续使用它程序中的对象调用关系过于复杂,实在难以弄清楚某个对象是否已经释放了内存。解决办法:应该重新设计数据结构,从根本上解决对象管理的混乱局面。4)忘记了释放内存,造成内存泄露。含有这种错误的函数每被调用一次就丢失一块内存。解决办法:动态内存的申请与释放必须配对,程序中new与delete的使用次数一定要相同,否则肯定有错误。1.6.10指针与动态内存16使用delete释放了内存后,没有将指针设置为NULL。导致产生“野指针”。“野指针”不是NULL指针,是指向“垃圾”内存的指针。char*pStrBuffer=newchar[256];delete[]pStrBuffer;*pStrBuffer=NULL;1.6.10指针与动态内存17内存操作注意事项:1)用new申请内存之后,应该立即检查指针值是否为NULL。防止使用指针值为NULL的内存。2)不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。3)避免数组或指针的下标越界,特别要当心发生“多1”或者“少1”操作。4)动态内存的申请与释放必须配对,防止内存泄漏。5)用delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”。1.6.10指针与动态内存18指针变量自身也有自己的内存,由于只需要保持一个内存地址,所以任何类型的指针大小都是四个字节。在代码栏编写以下代码,编译并查看输出:#include<iostream>usingnamespacestd;voidmain(){ char*pc; int*pi; short*ps; double*pd; cout<<sizeof(pc)<<endl; cout<<sizeof(pi)<<endl; cout<<sizeof(ps)<<endl; cout<<sizeof(pd)<<endl; system(“pause”);}1.6.11指针的内存地址19如果要保存指针的内存地址,则需要使用到二级指针。在代码栏编写以下代码,编译并查看输出:#include<iostream>usingnamespacestd;voidmain(){ intival=10; int*pi=&ival; int**ppi=π cout<<&pi<<endl; cout<<ppi<<endl; system(“pause”);}1.6.11指针的内存地址20void类型的指针可以保存任何类型数据的内存地址,只不过在访问数据或者修改数据的时候,需要将指针类型转换为所保存的数据类型。在代码栏编写以下代码,编译并查看输出:#include<iostream>usingnamespacestd;voidmain(){ intival=10; int*pi=&ival; void*pv=&ival; cout<<pi<<endl; cout<<pv<<endl; cout<<*(int*)pv<<endl; system(“pause”);}1.6.12void类型的指针21在32位机器中整型与指针都占4个字节,内存的表现方式也都是二进制整数,但是整型和指针所表示的数据类型不同。在代码栏编写以下代码,编译并查看输出,可以看到一个编译错误,无法从整型转换为整型的指针:#include<iostream>#include<windows.h>usingnamespacestd;voidmain(){ intival=0x18ff28; int*pi=ival; system(“pause”);}1.6.12void类型的指针22但是整型类型被强制转换为整型指针类型后,也可以给指针赋值,这个时候要注意的是指针保存的并不是整型数据所在的内存地址。在代码栏编写以下代码,编译并查看输出:#include<iostream>#include<windows.h>usingnamespacestd;voidmain(){ intival=0x18ff00; int*pi=(int*)ival; cout<<pi<<endl; cout<<*pi<<endl; cout<<&ival<<endl; system(“pause”);}1.6.12void类型的指针23本节介绍了如何使用指针创建动态内存的办法,以及如何释放动态内存和野指针的处理办法。运行int*pi=new
int(9);inti
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 门市出租合同范本
- 园林花木租赁合同格式
- 庭院房购房合同范本2024年
- 砌筑工程-砖砌体施工
- 股权投资公司抵押担保借款合同范本
- 关于离婚协议书范本建议
- 家政服务人员劳动合同案例
- 2024年幼儿食材配送协议样本
- 识别并规避劳动合同中的霸王条款
- 2024版产品买卖协议书格式示例
- 安徽省合肥市第五十中学西校区2024-2025学年期中考试七年级数学试题(无答案)
- 沪教版四年级上册期中复习数学试卷(一)
- 广东省广州市2024-2025学年上学期八年级数学期中复习试卷
- TWSJD 66-2024 放射工作人员职业健康检查技术指南
- 医院介绍课件模板
- 20世纪时尚流行文化智慧树知到期末考试答案2024年
- 第四章-国防动员
- 第一讲军事思想概论
- 普及人民代表大会制度知识竞赛试题库(1000题和答案)
- 兰亭序中楷毛笔临摹字帖(可打印)
- 单相智能电表硬件电路设计
评论
0/150
提交评论