【Objective-C】引用计数

一.基本概念:

顾名思义,自动引用计数 (ARC, Automatic Reference Counting )是指内存管理中对引用采 取自动计数的技术。以下摘自苹果的官方说明:

在Objective-C中采用Automatic ReferenceCounting (ARC) 机制,让编译器来进行内 存管理。在新 一代Apple LLVM编译器中设置ARC 为有效状态,就无需再次键入retain 或 者release 代码,这在降低程序崩溃、内存泄漏等风险的同时,很大程度上减少了开发程序 的工作量。编译器完全清楚目标对象,并能立刻释放那些不再被使用的对象。如此 一来,应 用程序将具有可预测性,且能流畅运行,速度也将大幅提升。

当一个对象的引用计数为大于0的计数,表示这个对象被持有不能被
释放,当引用计数为0时表示这个对象需要被释放掉。

引用计数

引用计数的原理:引用计数可以有效的管理对象的生命周期,当我们创建一个新对象的时候,它(该对象所在的内存块)的引用计数为1,当有一个新的指针指向这个对象时,我们将其引用计数加1,当某个指针不在指向这个地址时,我们将其应用计数减1,当对象的引用计数变为0时,说明这块内存不在被任何指针指向,这个时候系统就会将对象销毁,回收内存。从而达到管理内存的目的。

举例说明:
假设办公室里的照明设备只有一个。上班进入办公室的人需要照明,所以要把灯打开。而对 于下班离开办公室的人来说,己经不需要照明了,所以要把灯关掉。办公室的照明设备相当于该对象,办公室中的人数相当于该对象的引用计数器,来一个人办公室的引用计数器加一,走一个人引用计数器就减一,只要办公室有人这个灯就得开,没人的时候就可以关掉,相当于释放这个对象。

对照明设备所做的动作对 Objective- C对象所做的动作
开灯生成对象
需要照明持有对象
不需要照明释放对象
关灯废弃对象

二.内存管理的思考方式:

对象操作O bje ctive- C 方法
生成并持有对象alloc/new/copy/mutableCopy 等方法
持有对象retain方法
释放对象release 方法
废弃对象dealloc方法

1.自己生成的对象,自己持有

使用以下名称开头的方法名意味着自己生成的对象只有自己持有:

  • alloc
  • new
  • сору
  • mutableCopy
    例如:
id obj = [[NSObject alloc] init];

id obj = [NSObject new];

其中 [[NSObject alloc] init][NSObject new] 是完全一致的。

另外,根据上述“使用以下名称开头的方法名”, 下列名称也意味着自己生成并持有对象。

  • allocMyObject
  • newThatObject
  • copyThis
  • mutableCopyYourObject

但是对于以下名称,即使用alloc/new/copy/mutableCopy名称开头,并不属于同一类别方法。

  • allocate
  • newer
  • copying
  • mutableCopyed

2.非自己生成的对象,自己也能持有

用上述项目之外的方法取得的对象,即用alloc/new/copy/mutableCopy 以外的方法取得的对象,因为 非自己生成并持有, 所以自己不是该对象的持有者。

//取得非自己生成并持有的对象

id obj = [NSMutableArray array]:

//取得的对象存在,但自己不持有对象

[obj retainl;

//自己持有对象

从上述的举例可以看出,通过retain方法,非自己持有生成的对象跟用alloc/new/copy/mutableCopy方法生成并持有的对象一样,成了自己所持有的。

3.不再需要自己持有的对象时释放

自己持有的对象, 一旦不再需要,持有者有义务释放该对象。释放使用release方法。

//自己生成并持有对象
id obj = [INSObject alloc] init];

[obj releasel];

//释放对象, 指向对象的指针仍然被保留在变量obj 中,貌似能够访问, 但对象一经释放绝对不可访问。

如此,用alloc 方法由自己生成并持有的对象就通过 release 方法释放了。
自己生成而非自己 所持有的对象,若用retain 方法变为自己持有,也同样可以用release 方法释放。

//取得的对象存在,但自己不持有对象。
id obj = [NSMutableArray array];

// 自己持有对象。
[obj retain];

//释放对象 对象不可再被访问。
[obj release];

用alloc/new/copy/mutableCopy 方法生成并持有的对象,或者用retain方法持有的对象, 一旦 不再需要,务必要用release 方法进行释放。

用某个方法生成对象,并将其返还给该方法的调用方

- (id) allocObject {
	// 自己生成并持有对象
	id obj = (INSObject alloc] init];
	
	return obj;
}

//调用上边的方法,也可以取得非自己生成并持有的对象
id obj1 = [obj0 allocObject];

使用某个方法取得对象,但是不持有对象:

- (id)object {
	//自己持有对象
	id obj - [(Nsobject alloc] init]; 
	
	//取得的对象存在,但自己不持有对象
	[obj autoreleasel];
	
	return obj;
}

上例中,我们使用了autorelease 方法。用该方法,可以使取得的对象存在,但自己不持有对象。autorelease 提供这样的功能,使对象在超出指定的生存范围时能够自动并正确地释放 (调用release方法 )。

但是也可以通过retain方法将调用autoreleasel 方法取得的对象变为自己持有。
如下代码所示:

//取得的对象存在,但自己不持有对象
id obj1 = lobjo object];

//retain方法将调用autorelease 方法取得的对象变为自己持有。
//自己持有对象
[obj1 retain];

4.无法释放非自己持有的对象

对于用alloc/new/copy/mutableCopy 方法生成并持有的对象,或是用retain 方法持有的对象, 由于持有者是自己,所以在不需要该对象时需要将其释放。而由此以外所得到的对象绝对不能释 放。倘若在应用程序中释放了非自己所持有的对象就会造成崩溃。例如自己生成并持有对象后, 在释放完不再需要的对象之后再次释放。

// 自己生成并持有对象
id obj = IINsObject allocl init];

//对象己释放
[obj release];
//释放之后再次释放已非自己持有的对象,应用程序崩溃

[obj release];
//崩溃情况:
//再度废弃已经废弃了的对象时崩溃,访问已经废弃的对象时崩溃

或者在“取得的对象存在,但自己不持有对象”时释放。

- (id)object {
    //自己生成并持有对象
    id obj = [[NSObject alloc] init];

    //取得的对象存在,但自己并不持有
    [obj autorelease];
    
    return obj;
}

//调用上边的方法,可以取得的对象存在,但是并不持有
id obj1 = [obj0 object];

[obj1 release];
//释放了非自己持有的对象!
//这肯定会导致应用程序崩溃!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值