iOS 杂谈IOS

内存管理(1)-手动引用计数

2019-03-30  本文已影响0人  深度码农患者

什么是自动引用计数(ARC)

顾名思义,自动引用计数是指内存管理中对引用采用自动计数的计数,让编译器来进行内存管理。在新一代的Apple LLVM编译器中设置ARC为有效状态,就无需再输入retain或者release代码,这在降低程序崩溃,内存泄露等风险的同时,很大程度上减少了开发程序的工作量。而编译器完全清楚目标对象,并能立刻释放那些不再使用的对象,如此一来,应用程序将具有可预测性,且能流畅运行,速度也将大幅提升

手动引用计数(MRC)

说到自动引用计数,就不得不提手动引用计数。iOS内存管理中引用计数功能来标识使用一个对象的引用次数。引用计数的思考原则就是生成、持有、释放、废弃四个动作。这些有关NSObjective-C内存管理的方法,实际上不包含在改语言中,而是包含在Cocoa框架中用于OSX、iOS应用开发。Cocoa框架中的Foundation框架类库的NSObject类负担内存管理的职责。Objective-C内存管理中的alloc/retain/release/dealloc方法分别指代NSObject类中的alloc类方法、retain示例方法、release示例方法和dealloc示例方法、

自己生成的对象,自己持有
/*
*  自己生成并持有对象
*/
id obj = [[NSObject alloc] init];
/*
自己持有对象
*/
/*
*  自己生成并持有对象
*/
id obj = [NSObject new];
/*
自己持有对象
*/
非自己生成的对象,自己也能持有

用上述项目之外的方法取得的对象,即用alloc/new/copy/mutableCopy以外方法取得的对象,因为并非自己生成并持有,所以自己不是该对象的持有者。我们来使用alloc/new/copy/mutableCopy以外的方法看看。这里试用一下NSMutableArray类中的array类方法。

/*
* 取得非自己生成并持有的对象
*/
id obj = [NSMutableArray array];
/*
* 取得的对象存在,但是自己不持有对象
*/

源代码中,NSMutableArray类对象被赋值给变量obj,但是obj自己并不持有该对象。使用retain方法可以持有等一下。

/*
取得非自己生成并持有的对象
*/
id obj = [NSMutableArray array];
/*
* 取得的对象存在,但是自己不持有该对象
*/
[obj retain];
/*
自己持有该对象
*/

通过retain方法,非自己生成的对象跟用alloc/new/copy/mutableCopy方法生成并持有的对象一样,成为了自己所持有的。

疑问

通过[NSMutableArray array]生成的对象,并没有持有它,为何不会被释放?它与retain再release后的对象有何区别?
看代码实现,应该是类方法创建会自动将其加入AutoreleasePool,在超出作用域的时候再自动释放。

不在需要自己持有的对象时释放

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

/*
* 自己生成并持有对象
*/
id obj = [[NSObject alloc] init];
/*
*  自己持有对象
/*
[obj release];
/*
* 释放对象
* 指向对象的指针仍然被保留在变量obj中,貌似能够访问
* 但对象一经释放绝对不可访问,会产生野指针问题
/
/*
* 取得非自己生成并持有的对象
*/
id obj = [NSMutableArray array];
/*
* 取得的对象存在,但自己不持有对象
*/
[obj retain];
/*
*  自己持有对象
/*
[obj release];
/*
* 释放对象
* 指向对象的指针仍然被保留在变量obj中,貌似能够访问
* 但对象一经释放绝对不可访问,会产生野指针问题
* release必须在持有后调用,没有持有调用或重复调用都会导致crash
/
-(id)allocObject {
/*
*  自己生成并持有对象
*/
    id obj = [[NSObject alloc] init];
/*
*  自己持有对象
*/
    return obj;
}
/*
*  取得非自己生成并持有的对象
*/
id obj = [NSObject allocObject];
/*
* 自己持有对象
*/
-(id)object {
  id obj = [[NSObject alloc] init];
/*
  自己持有对象
*/
[obj autorelease];
/*
  取得的对象存在,但是将对象放入自动释放池,自己不持有对象
*/
return obj;
}
id obc1 = [NSObject object];
/*
*  取得的对象存在,但是自己不持有对象
*/
id obj1 = [NSObject object];
/*
*  取得的对象存在,但是自己不持有对象
*/
[obj1 retain];
/*
*  自己持有对象
*  注意,对象调用retain方法后必须调用release方法进行释放,否则会产生僵尸对象
/*
无法释放非自己持有的对象
/*
*  自己生成并持有对象
*/
id obj = [[NSObject alloc] init];
/*
*  自己持有对象
*/
[obj release];
/*
*  对象已释放
*/
[obj release];
// 释放之后再次释放已非自己持有的对象,应用程序将crash
// 再度废弃已经废弃了的对象和访问已经废弃的对象,都会造成crash
id obj = [NSObject object];
// 取得的对象存在,但自己不持有对象
[obj release];
// 释放了非自己持有的对象会导致crash
上一篇 下一篇

猜你喜欢

热点阅读