Objective-C中alloc/init对象释放的典型写法为何符合内存管理规则?
Objective-C中alloc/init后的内存释放疑问
根据Objective-C的内存管理规则,我们必须释放通过alloc创建的对象。比如这段常见的代码:
XYZClass *obj = [[XYZClass alloc] init]; // 使用obj [obj release];
但Apple文档明确提到,init方法有可能返回和alloc创建的不同对象,并且建议采用这种嵌套调用的写法。这就带来一个疑问:上面的代码释放的是init返回的对象,并没有直接释放alloc创建的那个原始对象,为什么还符合内存管理规则?
核心原因:init会自动处理原始对象的释放
当init方法决定返回一个与alloc创建的不同对象时,它内部会自动完成对原始alloc对象的释放操作。具体流程是这样的:
- 调用
[XYZClass alloc]会创建一个新对象(假设为对象A),此时我们拥有这个对象的所有权。 - 调用
[A init]时,如果init逻辑需要返回另一个对象(比如单例实例、缓存的复用对象,或者子类重写init返回父类实例等场景),它会先调用[A release]释放掉原始的对象A,然后返回新的对象B。 - 最终我们拿到的
obj是对象B,这个对象才是我们需要负责管理所有权的对象——要么是init内部新创建并让我们拥有的,要么是它通过其他方式获取但转移了所有权给我们的。
所以调用[obj release]释放的是我们实际拥有的对象,而原始的alloc对象已经被init妥善处理了,完全符合内存管理规则。
为什么建议嵌套调用?
如果把alloc和init分开写,会存在误操作的风险:
XYZClass *temp = [XYZClass alloc]; XYZClass *obj = [temp init]; [temp release]; // 错误:如果init已经释放了temp,这里再次release会导致野指针崩溃
嵌套写法[[XYZClass alloc] init]可以避免我们持有原始的alloc对象,从根源上杜绝这种误释放的问题,这也是Apple文档推荐它的原因。
内容的提问来源于stack exchange,提问作者Joseph Johnston
相关产品推荐
相关产品推荐

