第29条:理解引用计数

自动引用计数(Automatic Reference Counting, ARC

垃圾收集器:

从Mac OS X 10.8开始,“垃圾收集器”(gargae collector)已经正式废弃了。

每个对象都有个计数器,用以表示当前有多少个事物想令此对象继续存活下去。叫做“保留计数”(retain count),也可以叫“引用计数”(reference count)。

由三个方法操作计数器

reatain 递增

release 递减

autorelease 递减,自动释放池(autorelease pool,第34条) 

查看保留计数的方法:retainCount, 不推荐使用。

对象创建出来时,其保留计数至少为1。

当保留计数为零时,对象就回收了(deallocated),也就是说,系统会将其占用的内存标记为“可重用”(reuse)。

内存在“解除分配”(deallocated)之后,只是放回“可用内存池”(avaiable pool)。如果该内存没有覆写,那么对象仍然有效,这时程序不会崩溃。

为避免在不经意间使用了无效对象,一般调用完饭release之后都会清空指针。这时就能保证不会出现可能指向无效对象的指针,这种指针通常称为“悬挂指针”(dangling pointer,野指针)。

例:

  [xxxx release];

  xxxx = nil;

对象如果持有指向其他对象的强引用(strong reference),那么前者就“拥有”(own)后者。

引用的“根对象”

MAC OS X应用程序中,NSApplication对象

iOS应用程序中,UIApplication对象。

两者都应用程序启动时创建的单例。

属性存取方法中的内存管理

例:

-(void)setFoo:(id)foo {

  // [foo retain]; // 先保留新值

  // [_foo release]; // 再释放旧值

  // _foo = foo; // 更新实例变量,令其指向新值

  [_foo release];

  _foo = [foo retain];

}

顺序很重要。

假如还未保留新值就先把旧值释放了,而且两个值又指向同一个对象,那么,先执行的release操作就可能导致系统将此对象永久回收。而后续的retain操作则无法令这个已经彻底回收的对象复生,于是实例变量成了悬挂指针。

自动释放池:

autorelease,此方法会在稍后递减计数,通常是在下一次“事件循环”(event loop)时递减,不过也可能执行地更早些(自己创建的自动释放池)。

autorelease能延长对象生命期,使其在跨越方法调用边界后依然可以在存活一段时间。

一般用于方法中返回对象时。

例:

-(NSString *)stringValue {

  NSString *str = [NSString alloc]initWithFormat:@"%@",self];

  retrun [str autorelease];

}

保留环(retain cycle):

循环引用,无法释放

1、通常采用“弱引用”(weak reference,参见第33条)

2、或者从外界命令(nil循环中的某个对象不再保留另外一个对象。

这两种方法都可以打破保留环,从而避免内存泄漏。

原文地址:https://www.cnblogs.com/Pikdays/p/5742635.html