3

我有一个带有以下代码的 ARC 类:

[object doStuffWithObject:otherObject];

object-doStuffWithObject:方法是用ARC编译的,是这样的:

- (void)doStuffWithObject:(id)otherObject
{
    DoStuffHelper(object, otherObject);
}

DoStuffHelper,一个 C 函数,使用 ARC 编译(出于性能原因)。在DoStuffHelper中,我是否需要-retain在开始时为他们打电话objectotherObject最后为他们打电话-release

4

4 回答 4

2

请参阅避免导致您高级内存管理中使用的对象的重新分配:实用内存管理,其中他们指出“接收到的对象通常应该在整个调用方法的范围内保持有效”,即retain并且release不是必需的,除非使用以下警告:

这条规则偶尔会有例外,主要属于两个类别之一。

  1. 从基本集合类之一中删除对象时。

    heisenObject = [array objectAtIndex:n];
    [array removeObjectAtIndex:n];
    // heisenObject could now be invalid.
    

    当一个对象从一个基本集合类中移除时,它会被发送一个release(而不是autorelease)消息。如果集合是被移除对象的唯一所有者,则被移除对象(heisenObject在示例中)会立即被释放。

  2. 当一个“父对象”被释放时。

    id parent = <#create a parent object#>;
     // ...
     heisenObject = [parent child] ;
     [parent release]; // Or, for example: self.parent = nil;
     // heisenObject could now be invalid.
    

    在某些情况下,您从另一个对象中检索一个对象,然后直接或间接释放父对象。如果释放父级导致它被释放,并且父级是子级的唯一所有者,那么子级(heisenObject在示例中)将同时被释放(假设它发送的是释放而不是autorelease消息父母的dealloc方法)。

为了防止出现这些情况,您heisenObject在收到它时保留它,并在完成后释放它。例如:

heisenObject = [[array objectAtIndex:n] retain];
[array removeObjectAtIndex:n];
// Use heisenObject...
[heisenObject release];

如果您的辅助功能属于这些类别之一,我会感到惊讶。retain如果没有and ,你可能会很好release,但我只是为了充分披露而提及它。

显然,您可能需要自己的retainrelease如果您的函数出于其他原因需要它(例如,如果任务是异步的,或者如果您正在做一些不寻常的事情,对象必须超出调用方法的范围),但我怀疑您会提到如果你在做这些事情之一。

此外,如果您的实用程序函数正在创建和返回一个对象,那将是另一回事(例如,您通常会autorelease返回要返回的对象)。

于 2017-09-23T07:06:48.073 回答
1

DoStuffHelper 是一个 C 函数,不使用 ARC 编译(出于性能原因)。

您是否有任何性能测量显示 ARC 较慢?

通常,打开优化器生成的 ARC 可执行文件将比禁用 ARC(并由编译器优化)的相同代码更快。

这是因为编译器(和运行时)可以推断引用能够避免调用retainrelease(更糟糕的是autorelease),其中所述调用在正确的 MRR 代码中是强制性的。

如果您有一个不是这种情况的代码模式,我想捕获所述模式并提交错误。

(诚​​然,这是一个元答案。它质疑是否需要这样的 ARC-MRR 接口。维护了部分 ARC 和部分 MRR 的代码库,这种混合充满了脆弱性。)

于 2017-10-03T16:27:33.970 回答
1

在绝大多数情况下,您不会发现 ARC 比传统的保留/释放慢。您是否使用过 Instruments 来验证问题?

话虽如此,您不需要在 DoStuffHelper() 中保留/释放对象,因为在进入时 retainCount 已经 >= 1。如果将对象存储在静态或全局中,则需要保留它们。

于 2017-09-23T01:44:44.740 回答
1

不,DoStuffHelper 不是断言objector所有权的对象otherObject。它只是一个直接对它们进行操作的实用函数。实际上,它是 ARC 类的一部分,它已经对这些对象执行了完整的内存管理。

于 2017-09-23T01:46:48.020 回答