一、OS X Lion 和iOS 5引入的内存管理新功能——自动引用计数 在复习objective-c的内存管理同时,需要详解这个新功能带来的变化
1/1 什么时自动引用计数
自动引用计数(ARC ,automatic reference counting) 是指在内存管理中对引用录取自动计数的技术,让编译器来进行内存管理,默认设置ARC为有效状态的情况下,就可以不必再键入(retain release)
好处:
1)降低程序崩溃和内存泄漏的风险(内存泄漏是指:操作系统可提供的所有进程空间,在被某个进程榨干,结果就是程序运行的时间越长,耗费的内存越大,程序容易崩溃,那么这种状况都会在什么情况下发生呢:即程序创建了这么一块内存,但是没有一个指针指向它对它进行操作)
2)减少了程序开发的工作量
3)编译器完全清楚的知道那些是需要被释放的对象,哪些对象不再需要使用,这样程序将具有可预测性,运行的效率也会提高
1/2 那么在ARC出现之前,程序员们都是怎么样手工进行内存管理的呢??
需要对内存引用进行的操作步骤有: 生成对象-》持有对象-》释放对象-》废弃对象
那么内存管理的思考方式我们也必须要知道:
引用计数,不只是在计数而已:
a、自己生成的对象,自己持有(计数生成的可以是你自己生成的对象,自身持有)
b、非自己持有的对象,也可以自己持有(计数生成的可以是别人的对象,但是你可以引用,也可以自身持有)
c、不再需要自己持有的对象就释放(自己生成的对象,自身持有完之后,不想要了,那么你就可以释放)
d、非自己持有的对象无法释放(毕竟你跟它非亲非故)
我对内存管理的思考方式的理解是这样的:打个比方,你在商店里买了一个商品,那么你就可以拥有它一阵子,你朋友买了一个物品,你同样可以拥有它一阵子,当你觉得你不喜欢了,你可以选择抛弃这件物品,但是你没法跑去商店里把你不喜欢的商品全部抛弃吧
1/3 对象操作与oc方法的对应
生成——alloc/new/copy/mutableCopy
持有 ——retain
释放——release
废弃——dealloc
根据引用计数式的内存管理思考方式,逐一分析:
a、自己生成的对象自己持有
使用(alloc、new、copy、mutableCopy 开头的方法名意味着自己生成的对象自己持有)
id obj=[[NSObject alloc]init];
id obj=[NSObject new];
copy方法是基于NSCopying方法约定
mutableCopy方法是基于NSMutableCopying方法约定
两者的区别是copy生成的是不可变对象
但是,请注意:有些方法即便用了alloc/new/copy/mutableCopy 却并不满足自己生成自己持有这一思考模式,为啥呢?
因为除了要满足开头,还需要满足驼峰拼写法(newHello)后面紧跟大写字母
b、非自己生成的,同样可以自己持有
id obj=[NSArray array];
id obj =[NSMutableArray array];
取得了对象存在,但是自己不持有对象 即NSMutableArray类被赋给了对象obj,但是对象obj自己并不持有该对象,从而使用:
[obj retain]; 从而使自己持有对象(持有不是自己生成的对象是需要条件的)
c、不再需要自己持有的对象时释放
1)id obj =[[NSObject alloc]init]
obj生成并持有对象
[obj release];obj释放对象
如此,使用alloc方法由自己生成并持有的对象就通过release释放了。
2)那么自己生成/非自己生成且非自己持有的对象,如果通过retain使得自己持有的话,同样满足“自己生成自己持有” 同样可以通过release释放
id obj =[NSMutableArray array]; NSMutableArray :此时非自己生成也非自己持有
[obj retain];此时非自己生成但是自己持有
[obj release];此时,非自己生成但是自己持有的对象就会被释放
所以说:不管是不是自己生成的对象,只要自己持有了,就可以对它进行释放
被释放的对象将不能够再进行访问
3)当遇到通过方法生成自己对象,并将其返回给调用方时:
-(id) allocObject
{
id obj =[[NSObect alloc]init]; //自己生成并持有
return obj;
}
id obj1 =[obj0 allocObject];
同样满足自己生成并持有对象 并且allocObject也满足驼峰拼写
4)调用[NSMutableArray]不代表自己持有也不代表自己生成,只能算是自己取得对象存在的时候,要怎么实现?因为不能直接使用alloc/copy/mutableCopy/new 所以使用其它没有特殊代表的方法名
-(id)object
{
id obj =[[NSObject alloc]init]; 自己生成并持有
[obj autorelease]; 取得对象存在,但自己不持有对象?
return obj;
}
使用了autorelease方法,用该方法,可以使得得对象存在,但是自己不持有对象,autorelase提供这样的功能,时对象在超出自己制定的生存范围内能够自动并正确的释放。
那么同样是释放 autorelease和release 有什么区别??
release:立即释放
autorelease:把对象注册到autoreleasepool中去,当pool结束时,自动调用release
id obj0=[obj1 object];
可以取得对象的存在,但是不能持有对象,要知道在pool结束的时候,对象已经被释放掉了
当然,也可以通过retain来将已经取得的对象存在变成自己持有
id obj0=[0bj1 object];取得对象存在,但非自己持有
[obj0 retain]; 取得对象存在并自己持有
总结:通过retain 可以将非自己生成或者已经取得对象存在的对象变为自己持有
d、无法释放非自己持有的对象
当持有者不是自己的时候,我们无法对对象进行释放,一旦释放非自己持有的对象,就会造成程序崩溃
id obj =[[NSObject aloc]init];自己生成并自己持有
[obj release] 释放掉的对象,非自己持有也非自己生成
[obj releaes ]
程序崩溃,因为此时obj已经是非自己持有的对象了 而且无法访问一个已经被废弃的对象
以上对这四项的分析,就是“引用计数式内存管理”的思考方式。