41

有人可以向我解释__autoreleasing在以下示例代码块中的目的吗?

- (void)execute:(NSError * __autoreleasing *)error {
    // do stuff, possibly assigning error if something went wrong
}

我删除了__autoreleasing,一切似乎仍然编译/运行良好。我开始使用 obj-c post ARC,所以我从来没有真正学习/理解所有那些双下划线 thingamajigs。我已经阅读了ARC 过渡指南,但我并不完全理解他们的 NSError 示例。

4

1 回答 1

85

考虑 ARC 如何处理变量- 每个引用变量都有一个模式(隐式或显式):strongweak等。这种模式让 ARC 知道如何处理对该变量的读取和写入;例如,对于变量,读取不需要额外的操作,而写入需要在变量被新引用替换之前释放变量中的现有引用。ARC 需要知道任何变量的模式才能发挥作用。

现在考虑本身通过引用传递的变量,例如,对于您,execute您将按照以下方式进行调用:

NSError *myError = nil;
...
[someObject execute:&myError]; // pass the variable itself by reference, not the variables value

并且正文execute将包含一个分配,如下所示:

- (void)execute:(NSError * __autoreleasing *)error
{
   ...
   if (error != NULL)
      *error = [NSError ...]; // assign indirectly via the reference to a variable
   ...
}

现在对于间接赋值,ARC 需要知道被引用变量的模式,这样它就知道如何读写。这就是__autoreleasing声明中的内容,它告诉 ARC 它已经传递了对模式为autoreleasing的变量的引用,并告诉 ARC 如何读取和写入变量的内容。将假定删除__autoreleasing和默认模式,在这种情况下,我建议显式肯定是好的。

自动释放模式意味着变量包含一个不属于自己的引用,如果需要,读取应该保留而写入可以只写入。它主要用于通过引用传递的变量。

您可能会注意到,在上面的示例中,变量myError具有强模式(隐式),但它作为自动释放通过引用传递- 编译器通过引入临时自动释放变量、复制而不保留当前引用myError并传递作为参数的临时引用execute:。调用返回后,编译器会从临时 to 进行正常分配myError,这会导致释放任何旧引用并保留返回的引用。

有关更多详细信息,请参阅Apple 过渡到 ARC 发行说明

跟进评论

问:是__autoreleasing隐式设置的吗?

A:Apple 的文档并不具体,但Clang 文档说它是隐含的间接参数。如上所述,我建议明确,清晰是一件好事™。

问:位置重要吗?

A:是的,也不是……这是一个 C 声明,是问答题(“以下声明是什么……”)。限定符应该在两个星号之间,因为它是一个指向 object 的(类型变量)自动释放指针的指针,但 Apple 声明编译器是“宽容的”,但没有具体说明它宽容的内容。安全起见,把它放在正确的地方。

问:在做间接分配之前,你不应该测试error存在吗?NULL

A:当然你应该,在你做间接之前的某个地方。显示的代码只是一个大纲,这些细节被...'s 省略和覆盖了。然而,由于多年来它已经被提出了几次,也许我省略了太多,所以if添加了一个合适的。

于 2012-11-27T18:29:14.953 回答