【转载学习】OC学习笔记之OC对象的内存管理
一、为什么要做内存管理
相对于现在动不动就上T的硬盘外存来说,计算机的内存虽然也在提升在还是太小了,而现在的应用软件也十分吃内存,程序运行进程中如果不管理内存,如果有泄露,系统内存将会越用越小,对移动设备来说更是如此。苹果手机的内存只有那么大,如果应用程序不管理内存而占用了过多的内存,系统肯定是不允许的,引发的闪退给用户不好的体验,那这绝对算不上一个成功的应用开发。
程序在运行中,应该及时销毁已经不需要的变量或者对象,及时释放内存,以维持内存占用的动态平衡。
二、OC内存管理的目标
OC中内存管理的目标主要是任何继承根类NSObject后创建的OC对象,对基本数据类型我们不需要关心,系统可以自动回收。因为在内存中基本数据类型和OC对象的存放位置不同,前者是用栈存放,后者是用堆存放。
比如:int a = 1; int b = 2; Person *p = [[Person alloc] init];这几句代码在内存中的存放位置就分这两类。小桥这里回忆一MJ老师画过的图:
![](https://img-my.csdn.net/uploads/201405/08/1399519499_1630.png)
如图所示,基本数据类型的变量是用栈来临时存放的,当过期的时候系统会自动回收,如下面的测试图片:
![](https://img-my.csdn.net/uploads/201405/08/1399519499_9336.png)
上图说明,在main函数return之前,基本数据类型的变量占用的内存会自动被释放,而OC对象始终占用内存,注意:
这里的Person类型指针p也是基本类型,过期时也会被系统回收,这里的作用域是main函数,所以return之前,p指针变量还在。但是p所指向的Person对象在整个程序结束之前是一直占用内存的,如果p和a、b一样是mian中的局部变量,那么在return之前p可能就会被释放,如果p被释放那么问题来了,它指向的对象将成为匿名对象,因为对象还在,以后也不能够释放它,除非程序退出。
三、OC对象中的引用计数器
OC对象中都有4个字节的空间来存引用放计数器
![](https://img-my.csdn.net/uploads/201405/08/1399519498_1216.png)
作用:
引用计数器表示的是这个对象被引用的次数,alloc、new或者copy出一个新对象,它的引用计数器初值就为1。
一旦它的引用计数器为0,那么系统会毫不留情地回收这个对象,反过来说引用计数器不为0那么它就始终占用内存。于是如你所思,OC的内存管理就是通过平衡引用计数器来完成的,只要保证引用计数器在对象过期时成为0,那么在程序运行过程中就能动态释放过期对象,而避免内存泄露。但是,就小桥看来,保持对象引用计数器的平衡这几个字远没有表面看上去那么简单。
对单个独立的对象来说,计数器加1减1是清楚明白的,但是当对象与对象之间联系起来的时候,彼此计数器什么时候加1什么时候减1就变得复杂了。
![](https://img-my.csdn.net/uploads/201405/08/1399519498_1216.png)
作用:
引用计数器表示的是这个对象被引用的次数,alloc、new或者copy出一个新对象,它的引用计数器初值就为1。
一旦它的引用计数器为0,那么系统会毫不留情地回收这个对象,反过来说引用计数器不为0那么它就始终占用内存。于是如你所思,OC的内存管理就是通过平衡引用计数器来完成的,只要保证引用计数器在对象过期时成为0,那么在程序运行过程中就能动态释放过期对象,而避免内存泄露。但是,就小桥看来,保持对象引用计数器的平衡这几个字远没有表面看上去那么简单。
对单个独立的对象来说,计数器加1减1是清楚明白的,但是当对象与对象之间联系起来的时候,彼此计数器什么时候加1什么时候减1就变得复杂了。
每个对象有三个继承自根类的方法与内存管理相关。
retain: 发送rratin消息给对象,将对象的引用计数器加1 ,返回值为对象本身;
release:发送release消息给对象,将对象的引用计数器减1,没有返回值;
retainCount:获得对象当前引用计数器的值;
前两个就是维持OC对象引用计数器平衡的方法了,管理内存就是通过合适地调用这两个方法,使得对象能在过期时被系统回收,而不是等到程序退出才被回收,如果程序从手机开机就一直运行,那过期对象不就一直占用内存么?
僵尸对象:已经被系统回收的对象叫作僵尸对象,不能再访问。看一下小桥取消ARC并打开Xcode的僵尸对象管理后的测试:
![](https://img-my.csdn.net/uploads/201405/08/1399519497_5774.png)
野指针: 指向僵尸对象或者不能访问的内存的指针叫做野指针,比如上图中的p就是一个野指针,用野指针调用方法就会出上图中的错。
空指针: p = nil;或者 p =NULL;或者p = 0;这三个都是空指针,和野指针相反,在OC中用空指针调用方法是不会报错的。
五、对象遗言
最后小桥再复习一下对象被回收前系统给对象发送的消息,这也是对象最后的一个动作了------ dealloc
OC对象在销毁前都要调用这个方法,用以释放自己占用的资源,再调用父类的 dealloc方法,让父类做相同操作,最后完成所有资源的释放。 管理内存时都要重写这个方法,小桥重写下这个方法:
//
// 文件:Person.m
// 项目:博客笔记
//
// 作者:葬花 桥
// 日期:14-5-8
// 版权: Copyright (c) 2014年 itcast. All rights reserved.
//
#import "Person.h"
@implementation Person
- (void)dealloc
{
NSLog(@"调用了dealloc方法!");
[superdealloc];
}
@end
![](https://img-my.csdn.net/uploads/201405/08/1399519497_8116.png)