《Objective-C高级编程 iOS与OS X多线程与内存管理》3

内存管理篇: 3.autorelease

autorelease的实质:
将创建的对象加入到NSAutoreleasePool管理“数组”中,并告知ARC系统暂时不要对此对象进行处理。待pool对象在其所属的NSRunLoop循环一次完成,准备释放(drain)时,对“数组”中的所有对象依次调用release方法。此时ARC再对对象进行内存管理。

GNUstep的实现

GNUstep的版本使用了同NSMutableArray一样的连接列表,将被标记的对象加入到“正在使用中的”autoreleasePool对象中。

// NSObject.m中:
- (id)autorelease {
    [NSAutoreleasePool addObject:self];
}


// NSAutoreleasePool.m中:
+ (void)addObject:(id)anObj {
    NSAutoreleasePool *pool = 获取正在使用中的pool;
    if (pool != nil) {
        [pool addObject:anObj];
    } else {
        ...
    }
}

- (void)addObject:(id)anObj {
    // 加入到内部管理的数组中
    [array addObject:anObj];
}
方法调用优化:在GNUstep实现的版本中,为了提高autorelease方法执行的速度,使用了“IMP Caching”的方式,及将函数指针提前缓存,需要时跳过了“objc_msgSend”的过程,直接调用:
// NSObject.m中:

// 缓存类名
id autorelease_class = [NSAutoreleasePool class];
// 缓存方法名
SEL autorelease_sel = @selector("addObject:");
// 缓存方法实现(函数指针)
IMP autorelease_imp = [autorelease_class methodForSelector:autorelease_sel];

- (id)autorelease {
    // 直接调用
    (*autorelease_imp)(autorelease_class, autorelease_sel, self);
}

注意:
由于NSAutoreleasePool覆盖了autorelease的方法实现(其他对象执行的是NSObject的实现),对pool对象发送autorelease消息会抛出异常。
不能对NSAutoreleasePool对象调用autorelease方法。

  • 补充:无论编译环境是否为ARC有效,都推荐使用@autoreleasepool块作为替代,以提高代码可读性。

你可能感兴趣的:(《Objective-C高级编程 iOS与OS X多线程与内存管理》3)