使用 __weak 到 ARC 中的局部变量

use __weak to local variable in ARC

当您在 ARC 中编写如下代码时

__weak NSMutableArray* array = [[NSMutableArray alloc] init];

编译器会向您显示警告或错误,并显示 "Assigning retained object to weak variable. object will be released after assignment"。

但是如果你这样写:

__weak NSMutableArray* array = [NSMutableArray array];

没有错误。

我想知道第二种用法在某些情况下是否合理?从内存管理的角度来看,这两个代码有什么区别?它是如何工作的?

它们是相同的,因为您会立即丢失对象。除了 alloc init 之外,编译器可能不知道对象将丢失。

可能存在编译器无法识别的非常细微的差异。

让我们来看一个不可变的版本:[NSArray array] 每次都可以 return 完全相同的静态对象。所以你的弱变量将指向一个有效的对象,它在其他地方有一个强引用。或者想想单例模式。另一方面,在调用 alloc/init 时,惯例规定您是该对象的唯一所有者,这通常会让您一无所有。

此外,工厂方法当然看起来更像是一个(函数式)方法。在任何情况下,它都不能很好地传达它 return 的所有权。对于自动释放的对象,不清楚您是唯一所有者还是共享所有者。

在第一种形式中,方法return是一个保留的对象。 ARC 确保在调用点上没有强引用时释放对象。这是 立即 正确的,具有弱引用 - 因此,编译器发出警告或错误。

在第二种形式中,方法 return 是一个 未保留的 对象。在这种情况下,编译器必须确保对象在 return 边界内仍然有效。当从这样的函数或方法中 returning 时,ARC 在 return 语句的评估点保留值,然后离开所有局部范围,然后平衡保留,同时确保值存在越过调用边界。也就是说,存在编译器创建的强引用。这个强引用会被编译器生成的代码自动释放。

因此,在这种情况下,没有错误或警告。

在最坏的情况下,持有该对象可能需要使用自动释放池。然而,编译器可以应用某些优化来避免这种情况。因此我们不应该假设 returned 对象存在于自动释放池中。

查看规格:http://clang.llvm.org/docs/AutomaticReferenceCounting.html#id14

另见关于 SO 的这个问题:Difference between [NSMutableArray array] vs [[NSMutableArray alloc] init]