第7章:内存管理
一、内存分配方式
1、静态区域分配:在程序编译期间就已经分配好的,例如全局变量、static变量
2、在栈上分配:函数内部的局部变量
3、从堆上分配(动态分配):通过malloc或者new开辟的空间
二、常见的内存错误及其对策
1、内存错误----->解决措施
a、内存未开辟成功,却使用它----->应该用if(NULL == p)或者if(NULL != p)来判断是否开辟成功
b、内存开辟成功,但未初始化就使用----->在内存开辟成功的时候就赋初值
c、内存分配成功也初始化,但操作越过了内存的边界(内存越界):----->
d、忘记释放内存)内存泄漏:----->malloc与free的使用次数一定要相同(new与delete一样,使用次数要相同)
e、释放了内存却继续使用它(野指针):----->释放内存后紧接着将指针设置成null;不要返回栈内存上开辟的空间的地址
总结:
1、用malloc和new申请内存后,应立即检查指针值是否为NULL
2、不要忘记为数组和动态内存赋初值
3、避免数组或指针的下标越界
4、动态内存的申请与释放必须配对,防止内存泄漏
5、用free或delete释放内存之后,立即将指针设置为NULL
三、指针与数组相比
1、同时指向字符串的时候:数组可以改变任意位置的内容,而指针不可以,因为其指向的空间是一个字符串,字符串的内容不能进行修改
2、不能对数组名进行直接复制与比较(若想将数组内容赋给指针,只能用strcpy,比较也只能用strcmp)
3、当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针,其余的时候均是数组
四、指针参数传递内存
1、指针作为实参,传递的是指向空间的地址,如果该指针为空,则传递失效,无论形参怎么改变对实参都无任何作用
2、形参可以用一个二级指针去接收实参的一级指针的地址(可以直接改变实参指针的指向空间)
3、不要用return语句返回栈内存指针
五、free与delete
只是把指针所指向的空间释放掉,但指向该空间的指针还在,空间释放后该指针会变成野指针。
六、动态内存释放
1、指针消亡了但是动态开辟的空间并没有释放---->在指针消亡之前释放掉该空间
2、内存被释放了,并不表示指针会消亡或者成了NULL指针----->及时把指针指向空
七、杜绝野指针
野指针的形成原因:
a、指针变量没有初始化
b、指向空间被释放后没有及时置为NULL
c、指针操作越过了变量的作用域
八、malloc与new
这一部分是我自己总结的(并非书本上的知识):
(1)malloc和free是函数,new和delete是操作符
(2)malloc申请空间不会初始化,new可以初始化
(3)malloc申请空间是,需要手动计算空间大小并传递,new只需要在其后跟上空间的类型即可
(4)malloc的返回值为void*,在使用时必须进行强转,new不需要,因为new后跟的是空间的类型
(5)malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
(6)申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造/析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理
(7)new/delete比malloc/free的效率稍微低一点,因为new/delete底层封装了malloc/free
1、new/delete、mallloc/free必须配对使用
2、new不是库函数,mallloc是库函数.
九、内存耗尽怎么办?
1、判断指针是否为NULL,如果是则马上用return语句终止本函数
2、判断指针是否为NULL,如果是则马上用exit(1)终止整个程序的运行
3、为new和malloc设置异常处理函数
十、malloc/free的使用要点
1、malloc的返回值是void*,所以要进行显示的类型转换
2、malloc只关心要开辟空间的字节数
十一、new/delete的使用要点
1、new在创建动态对象的时候同时完成了初始化工作
2、如果用new创建数组,那么只能使用对象的无参构造函数
3、在使用delete释放对象数组时,留意不要丢弃了符号‘[]’