gpt4 book ai didi

objective-c - 声明方法参数 __autoreleasing 有什么好处?

转载 作者:太空狗 更新时间:2023-10-30 03:36:27 24 4
gpt4 key购买 nike

根据 Transitioning to ARC Release Notes :

__autoreleasing is used to denote arguments that are passed by reference (id *) and are autoreleased on return.

例如:

-(BOOL)performOperationWithError:(NSError * __autoreleasing *)error;

但是与以下相比,上述的优点是什么:

-(BOOL)performOperationWithError:(NSError * __strong *)error;


更新:

有几个答案提到了编译器处理 var 和参数之间不匹配的临时 var 技巧作为 __autoreleasing优势。我不明白为什么编译器不能为 __strong 参数做同样的事情。我的意思是,对于 __weak var 和 __strong 参数,编译器可以类似地这样做:

NSError * __weak error;
NSError * __strong tmp = error;
BOOL OK = [myObject performOperationWithError:&tmp];
error = tmp;
if (!OK) {
// Report the error.
}

编译器知道 -(BOOL)performOperationWithError:(NSError * __strong *)error; 返回一个强引用(+1)所以它像任何 new 一样处理它 -家庭法。由于 tmperror 存在于相同的范围内,只要 error 存在,编译器就可以合理地保持它的存在,因此 __weak reference(error) 现在由 __strong reference(tmp) 支持,并且在范围结束之前不会被取消。

最佳答案

tl;dr

在这种情况下,将 __weak 对象隐式转换为 __strong 对象会改变程序的语义,这是编译器永远不应该做的事情。


场景

举个例子

NSError *error;
BOOL success = [myObject performOperationWithError:&error];
if (!success) {
// Report the error
}

在这种情况下,error 局部变量被 ARC 自动推断为 __strong

同时

error参数
-(BOOL)performOperationWithError:(NSError * __autoreleasing *)error;

NSError * __autoreleasing * 类型。

请注意,在任何情况下,ARC 都会将通过引用 (id *) 传递的参数推断为 id __autoreleasing * 类型,因此上述签名等同于

-(BOOL)performOperationWithError:(NSError **)error;

在 ARC 下。

因此我们有一个不匹配,因为我们将一个 __strong 注释变量传递给一个需要 __autoreleasing 参数的方法。

引擎盖下

在我们的示例中,编译器将通过创建本地 __autoreleasing tmp 变量来解决此类不匹配问题。

代码变为

NSError * __strong error;
NSError * __autoreleasing tmp = error;
BOOL success = [myObject performOperationWithError:&tmp];
error = tmp;
if (!success) {
// Report the error.
}

替代方案

现在假设我们可以更改 performOperationWithError: 的签名。

如果我们想避免使用 tmp 变量的“编译器技巧”,我们可以将我们的签名声明为

-(BOOL)performOperationWithError:(NSError * __strong *)error;

我们有一个 __strong 变量,现在我们将它传递给一个需要 __strong 参数的方法,所以我们刚刚消除了不匹配。

看起来不错,为什么不总是声明 __strong 参数?

一个原因是将参数声明为 __autoreleasing 将使该方法接受甚至是 __weak 引用。

在当前示例中它没有多大意义,但在某些情况下我们希望通过引用传递一个 __weak 变量并声明 __autoreleasing (或离开 ARC 来推断它)将使我们能够这样做。

ARC 将应用上面看到的相同技巧,创建一个 __autoreleasing tmp 变量。

结论

目前介绍的机制名为pass-by-writeback

这种机制被设计为与__autoreleasing__strong__weak 变量一起工作,因此程序员可以安全地依赖类型推断由编译器生成,不太关心周围的注释变量。

声明一个 id __strong * 参数在某些情况下可能有意义,但通常它可能导致编译器生成意外错误。

我的建议是:“让编译器发挥他的魔力,你就会好起来的”

更新

I don't see why compiler can not do the same trick for __strong argument.

告诉编译器以 __autoreleasing 方式处理 __strong__weak 变量的管理没问题,因为它基本上意味着:“请编译器自动执行正确的操作。”

这就是为什么上面看到的技巧可以毫无问题地工作。

另一方面,如果您将变量声明为 __weak,您可能有充分的理由这样做,并且您最不想做的就是在您明确指定时隐式保留它。这会从根本上改变您编写的代码片段的语义,因此编译器不会那样做(谢天谢地!)。

换句话说

__weak --> __autoreleasing
__strong --> __autoreleasing
__weak <--> __strong 错了!

关于objective-c - 声明方法参数 __autoreleasing 有什么好处?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14554121/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com