内存管理基础 - Objective C

Posted

技术标签:

【中文标题】内存管理基础 - Objective C【英文标题】:Memory Management Basics - Objective C 【发布时间】:2010-02-09 20:23:24 【问题描述】:

我有一个关于对象、内存和保留的一般性问题。

我不是一个完整的新手(我在 iTunes Store 上有待售的应用程序),但一定有什么东西从我身边溜走了。我使用 Google Docs API,昨天我下载了一个电子表格提要,并列举了结果,即电子表格记录提要。

在枚举对象并将对象添加到字典后,字典在循环进入下一个记录之前被添加到数组中。所以经过 5 次后,数组有 5 个对象,每个记录一个字典,每个对象都有值。奇怪的是,最后,阵列有 5 个相同信息的副本。每次循环时,字典都会按预期发生变化,但是当我将其插入数组时,数组中的其他对象会更改为匹配。

我在 *** 上浏览了一些东西,并找到了一个尝试这个的建议:

[array insertObject:[dictionary copy] atIndex:0];

这解决了它。添加复制方法使一切正常。

我只是想知道为什么。

【问题讨论】:

【参考方案1】:

通常,当一个对象被放入数组时,即使原始对象被修改或销毁,它也会保持原样。

你错了。数组(以及 Cocoa 中的所有其他容器类)永远不会那样工作。它们只存储对它们包含的对象的引用(并保留它们),因此如果您从数组中检索它们(因为它们是相同的对象),原始对象中的任何更改都会反映出来。

当然,通过调用copy,您正在创建字典的副本,所以现在您正在处理单独的对象。同时,您现在正在泄漏内存,因为您负责释放从copy 返回的对象。

另外,请记住,copy 仅进行 复制,因此复制的字典的实际内容不会被复制。如果您更改字典的内容,这些更改将反映在两个字典中(“原始”字典和您添加到数组中的复制字典)。

【讨论】:

感谢您的回复。我接受了你引用的部分,所以我看起来不像这样一个白痴(所以没有其他人感到困惑)。在循环中将 NSDictionary 对象添加到 NSArrays 的最佳做法是什么? 最佳做法是避免在集合中包含变异对象,如果必须这样做,请将它们视为具有放射性。【参考方案2】:

当您将一个对象(我们称之为 X)插入到数组中时,实际放入数组中的是指向 X 的 指针 的副本,而不是 X 本身的副本。 X 被发送了一个retain 消息,以便数组可以保留它,但X 没有发送一个copy 消息。这意味着稍后对 X 的更改影响“存储”在数组中的对象。

警告:建议的解决方案会导致大量内存泄漏,因为复制的数据永远不会被释放。更好的解决方案是自动释放复制的数组,这样在数组释放的时候就会释放。

[array insertObject:[[dictionary copy] autorelease] atIndex:0];

或者,对于 iPhone 代码(其中autorelease can be bad,尤其是在循环中):

NSDictionary * newDict = [dictionary copy];
[array insertObject:newDict atIndex:0];
[newDict release];

更新:请务必阅读Ole Begemann's answer。他对字典的深拷贝和浅拷贝提出了很好的观点。

【讨论】:

谢谢!在循环中将 NSDictionary 对象插入 NSArray 对象的最佳做法是什么?我应该在开始时分配一个新字典并在每个循环结束时释放吗?我在最后取出了部分,以免混淆其他人。另外,所以我看起来不像这样的工具 是的,这是一种更好的方法。不建议 iPhone 应用程序使用 Autorelease,尤其是在循环中。我修改了答案并添加了指向一些支持信息的链接。完全披露:链接的问题是我的:)

以上是关于内存管理基础 - Objective C的主要内容,如果未能解决你的问题,请参考以下文章

Objective C - 内存管理和自动释放???

一个简单的 Objective C xcode 内存管理问题

带有块、ARC 和非 ARC 的 Objective C 内存管理

在 Objective C++ 中管理内存需要了解啥?

Objective-C 的内存管理帮助

iOS基础 ----- 内存管理