objective-c - 另一个 "Retain, then Release"问题

标签 objective-c cocoa memory-management retaincount

作为一名 Cocoa/Obj-C 新手,我正在阅读 Aaron Hillegass 所著的《Mac OS X 的 Cocoa 编程》一书,并且 - 抛开现在我们还有机会使用 GC 来避免所有这些推理这一事实 -我不确定我是否明白其中一些保留的原因。

特别是 Aaron 给出的一个良好编程实践的示例:

- (void) setFoo:(NSCalendarDate *)x
{
    [x retain];
    [foo release];
    foo = x;
}

我不明白在方法的第一行保留 x 实例的原因:

[x retain];

这个实例的作用域只是set方法,对吧? 当退出方法作用域时,x 实例无论如何都应该被释放,不是吗? 此外,当将 x 分配给 foo 时:

foo = x;

foo 无论如何都会指向 x 个内存单元,因此会增加指向的对象保留计数,不是吗?这应该确保内存不会被释放。

所以,有什么意义呢?当然,我确信我错过了一些东西,但不知道到底是什么。

谢谢, 法布里齐奥

最佳答案

Retain 的意思是:我需要保留这个对象,它不能被释放。如果 x 不被保留,则可能会发生以下情况:

您将 x 分配给 foo,因此 foo 现在指向您的 NSCalendarDate 所在的地址。有人释放或自动释放该对象,它的保留计数最终降至 0,并且该对象被释放。现在您的 foo 仍然指向该地址,但不再是有效的对象。一段时间后,创建一个新对象,并且它碰巧位于与旧 NSCalendarDate 对象相同的地址。现在你的 foo 指向一个完全不同的对象!

为了防止这种情况,您需要保留它。你需要说,请不要释放该对象,我需要它。一旦你完成它,你释放它,这意味着我不再需要该对象,如果没有其他人需要它,您现在可以清理它。

现在进行经典的三部分作业。考虑一下您的 setFoo: 看起来像这样:

- (void) setFoo:(NSCalendarDate *)x
{
    [foo release];
    [x retain];
    foo = x;
}

这是一个非常糟糕的主意。考虑您的对象是唯一保留 NSCalendarDate 对象的对象,并考虑您将执行:[self setFoo:foo];。可能听起来很愚蠢,但这样的事情可能会发生。现在的流程是这样的:

  1. foo 将被释放。它的保留计数现在可能会下降到 0,并且该对象将被释放。
  2. 哎呀,我们正在尝试保留并访问已释放的对象。

这就是为什么您总是首先保留新对象,然后释放旧对象。

如果您有 Java 或 .NET 背景,了解 Foo * 类型的变量仅包含对象的地址非常重要,仅此而已。在 Java 或 .NET 中,如果您愿意,指向对象的变量会自动“保留”该对象。在 Objective-C 中并非如此(在非 GC 环境中)。您可以将 Foo * 类型的变量视为弱引用,并且您明确需要告诉 Objective-C 您是否仍需要该地址处的该对象。

关于objective-c - 另一个 "Retain, then Release"问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6213192/

相关文章:

xcode - Mac 上的蓝牙 RSSI/查询扫描 - 无需连接即可检测到 iPhone 的接近度?

java内存管理-java类加载器

C malloc 函数大小

objective-c - NSError __autoreleasing 与 _Nullable

iphone - 自定义 CorePlot gridLineStyle

使用 ZBarSDK 时 iPhone 相机失去自动对焦

ios - 如何将 NSString 转换为 Int?

objective-c - 如何在 Cocoa 中制作一个未装饰的窗口?

objective-c - NSWindow - 右键单击​​菜单

c - Micriμm μC/OS-III RTOS 中的分配和释放