【问题标题】:NSMutableArray arrayWithCapacity vs initWithCapacityNSMutableArray arrayWithCapacity 与 initWithCapacity
【发布时间】:2011-03-08 23:52:06
【问题描述】:

我是一名 iPhone/Objective-C 新手,具有广泛的 Java 背景。

我正在学习更多关于 Objective-c 内存管理的知识,并且我正在阅读 Apple 关于内存管理的文档:http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

在“对象所有权策略”部分中,它表示您拥有通过以 alloc、new 或包含副本开头的方法创建的任何对象。所有权意味着您需要在完成对象后显式地release

所以我正在查看 NSMutableArray 文档:http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html

有两种方法几乎可以做同样的事情......它们都创建了一个具有一些初始容量的数组。一个是类方法,一个是实例方法。

+ (id)arrayWithCapacity:(NSUInteger)numItems;
- (id)initWithCapacity:(NSUInteger)numItems;

现在作为一个懒惰的 Java 开发人员,我为什么会选择实例方法而不是类方法,因为我知道在某个时间点我必须自己清理?

我想我可能在这里遗漏了一个基本点...这仅仅是确定何时对象被释放的问题吗?类方法中的autorelease 与实例方法中的release?我想在资源非常有限的平台(iPhone)上,我应该避免使用类方法并在完成后立即释放对象?

谢谢!

【问题讨论】:

    标签: iphone objective-c memory-management


    【解决方案1】:

    您通常会根据您是否将拥有该对象的时间超过当前方法的生命周期来选择(例如,将其分配给一些静态或直接分配给 ivar)。在这种情况下,您可以使用 alloc/init 方法,因为您知道自己想要拥有它。如果你打算只在当前方法的范围内使用它,或者你将它分配给像属性这样管理的东西,那么你可能会使用便捷方法。

    当你知道你将拥有一个你正在创建的对象时,alloc/init 调用总是比便利/保留方式更有效,因为后者需要基本上分配/初始化/自动释放对象,然后归还时您保留它。

    当您在循环中分配并且不需要/不想处理自动释放池时,您也可以使用直接 alloc/init 方法。

    【讨论】:

    • 现在我们有了自动引用计数,这是否真的如此?在我看来,这两种方法现在必须几乎相同,因为 ARC 代码现在基本上将隐式自动释放应用于 alloc/init 创建的对象。可以看出,如果我理解正确的话,大多数情况下我们应该使用方便方法,如果存在的话,因为没有任何性能损失。
    【解决方案2】:

    arrayWithCapacity: 已经应用了自动释放。

    initWithCapacity: 明确保留,您需要自己释放它。由于您通常将其称为 [[A alloc] init...],因此这将触发一个灯泡“我需要为此管理内存”,除了“alloc”是“新”和“复制”之外的其他类似魔术词您阅读了内存管理指南。但是从你的问题来看,你似乎很了解它的原理。

    您是正确的,您应该将内存占用保持在低水平,但这并不意味着您需要始终进行显式的初始化/释放。正如 Nick 所说,使用自动释放工厂方法的一个用例是当您将它们作为参数传递时。

    另一个例子是,当您向 NSDictionary 或 NSArray 之类的集合添加某些内容时,可以使用 autorelease 工厂方法创建“某些内容”,因为该集合“接管”了保留它。 (添加到集合时会保留,移除时会释放。)

    你可能会争辩

    Blah *blah = [Blah blahWithSomething];
    [myMutableArray addObject:blah];
    

    比打字更干净

    Blah *blah = [[Blah alloc] initWithSomething];
    [myMutableArray addObject:blah];
    [blah release];
    

    在第一种情况下,您根本不需要担心发布调用。不利的一面是,当您在同一个运行循环中多次执行此操作时,如果它是在运行循环结束时消失的临时/一次性数组对象,则第一种情况的内存占用更大。但如果它是一个小对象,不是在循环中完成并像常见情况那样保留更长时间,它们的足迹是相同的。

    【讨论】:

      【解决方案3】:

      在这种情况下,我尝试遵守以下规则以避免与内存相关的(==“非常讨厌”)错误:

      • 如果您将该数组作为参数传递,那么您可以使用工厂方法没问题,因为保留/释放它是接受函数的责任
      • 如果要继续使用对象,请使用初始化方法并在最后释放对象

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-26
        • 1970-01-01
        • 2011-10-13
        • 2011-08-29
        • 1970-01-01
        • 2012-01-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多