【问题标题】:Does NSArray:lastObject return an autoreleased object?NSArray:lastObject 返回一个自动释放的对象吗?
【发布时间】:2010-05-23 23:12:51
【问题描述】:

我正在处理一个 iPhone 项目,我想从 NSMutableArray 中检索一个对象,从数组中删除该对象,然后再使用它。代码如下所示:

NSMutableArray * array;
// fill the array
NSObject * obj = [array lastObject];
[array removeLastObject];
// do something with obj (in the same function)

array 是唯一对正在访问的对象具有保留的实体。这样做安全吗?我会假设这只有在 lastObject 自动释放对象时才有效,而我无法弄清楚它是否会这样做。

【问题讨论】:

    标签: iphone objective-c cocoa


    【解决方案1】:

    为什么不打电话

    [array removeLastObject]
    

    在你的函数结束时?那是更少的释放/保留。它可能会使您的代码更具可读性/不那么混乱。

    备案Apple documentation

    像 NSArray 一样,实例 NSMutableArray 保持强大 参考他们的内容。如果你 不要使用垃圾收集,当 将对象添加到数组中, 对象收到保留消息。什么时候 一个对象从一个可变对象中移除 数组,它接收一个释放消息。 如果没有进一步的参考 对象,这意味着对象 被解除分配。如果你的程序保持 对此类对象的引用, 参考将变为无效,除非 您向对象发送保留消息 在从数组中删除之前。 例如,如果 anObject 不是 在将其从 数组,下面的第三个语句可以 导致运行时错误:

    id anObject = [[anArray objectAtIndex:0] retain]; 
    [anArray removeObjectAtIndex:0]; 
    [anObject someMessage];
    

    【讨论】:

    • 为了明确这一点:NSArray 和 NSMutableArray 类对一般规则有例外,即从名称不包含“new”、“copy”或“alloc”的方法返回的对象返回自动释放的对象. 这意味着原问题中的代码是不安全的。
    • @harms 这条规则不只适用于对象创建吗?
    • @harms:没有一般规则从名称不包含“new”、“copy”或“alloc”的方法返回的对象返回自动释放的对象。唯一的规则是您不拥有此类一个对象。
    • @sylvanaar 不,规则是通用的,但其结果是授予所有权的方法通常是创建方法,当然还有retain
    • @JeremyP 和@Nikolai Ruhe:我现在重新阅读了 Cocoa 内存管理规则,我是对的。请参阅“共享对象的有效性”部分。它声明:“Cocoa 的所有权策略指定接收到的对象通常应该在整个调用方法的范围内保持有效。”它继续说:“这个规则偶尔会有例外[...]当一个对象从一个基本集合类中删除时,它会被发送一个释放(而不是自动释放)消息。”
    【解决方案2】:

    这里值得一提的是Cocoa Memory Management Rules。如果您在非 GC 环境中工作,例如iPhone,总是值得一提的。

    基本规则状态:

    如果您使用名称以“alloc”或“new”开头或包含“copy”的方法(例如,alloc、newObject 或 mutableCopy)创建对象,或者向其发送保留消息。您有责任放弃使用 release 或 autorelease 拥有的对象的所有权。其他任何时候您收到物品时,都不得释放它。

    很明显,您没有通过 alloc、new... 或包含副本的东西获得 obj。所以你不拥有它。

    在您的代码中,第二个推论也是相关的:

    接收到的对象通常保证在接收它的方法中保持有效(例外情况包括多线程应用程序和一些分布式对象情况,尽管您还必须小心修改从其中接收到另一个对象的对象)。该方法也可以安全地将对象返回给它的调用者

    我已将相关部分加粗。您已经修改了从中接收对象的数组,因此它可能会消失。您可以在将对象从数组中删除之前保留该对象,或者在完成该对象后进行删除。

    实际上,即使使用问题中的代码,您 可能 也是安全的,因为 NSMutableArray 的 objectAtIndex 实现:可能在返回项上执行保留,然后自动释放。在多线程环境中,这是保证对象在足够长的时间内保持有效以将其返回给调用者的唯一方法。但是,我没有看到 NSMutableArray 的代码,所以不要依赖它。

    ETA:刚刚查看线程编程指南,似乎 NSMutableAtray 不做保留,自动释放。

    【讨论】:

    • 感谢您的回答,最后一行非常有用
    【解决方案3】:
    NSObject * obj = [array lastObject]; // Just returns an object, its retain count not changed
    [array removeLastObject]; // object receives release message
    

    因此,如果您的数组是唯一保留您的对象的实体,那么在删除它之后,它的保留计数变为零,并且应该被释放。为了安全地使用该对象,您应该保留它并在不需要时释放它:

    NSObject * obj = [[array lastObject] retain];
    [array removeLastObject];
    // do something with obj (in the same function)
    [obj release];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-18
      • 2011-06-23
      • 1970-01-01
      • 2011-12-15
      相关资源
      最近更新 更多