浅谈自动引用计数——内存管理思考方式

一、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已经是非自己持有的对象了 而且无法访问一个已经被废弃的对象

以上对这四项的分析,就是“引用计数式内存管理”的思考方式。

原文地址:https://www.cnblogs.com/CityPe/p/5343768.html