内存管理属性如何影响数组的单元格



在我的iPhone开发书中,我看到了一些奇怪的编码示例,关于当对象被添加到数组中时数组做什么以及当整个数组被释放时。一个代码示例在实例数组上具有以下属性:

@property (nonatomic, retain) NSMutableArray* myArray;

作者向数组中添加一个对象,然后立即释放指向该对象的指针。数组单元格现在不会指向垃圾数据吗?除非在幕后,数组单元格在添加对象时保留该对象。

SomeObject* someObject = [[SomeObject alloc] init];
[self.myArray addObject:someObject];
[someObject release];

作者还释放了指向数组的指针,而没有首先遍历每个数组单元格并释放单个对象。这是一个内存泄漏,除非在幕后,每个单元都被发送一个释放消息。

- (void)viewDidUnload {
    self.myArray = nil;
    [super viewDidUnload];
}

除非在幕后,数组单元格在添加对象时保留该对象。

是的,这发生了。

…除非,在幕后,每个单元都被发送了一个释放消息。

这也会发生。

你已经回答了自己的问题。

下面是引用自集合编程主题:

当你将一个对象添加到NSMutableArray对象不会被复制,(除非你将YES作为。的论证initWithArray: copyItems:)。相反,一个对象直接添加到数组中。在托管内存环境中对象接收到保留消息这是添加;在垃圾收集中环境,它是强有力的引用。当数组为在托管内存中被释放环境中,每个元素发送一个发布消息。

不像在C或c++中,你经常担心是否删除一个对象,因为担心它仍然在其他地方被使用,Objective-C(或者更确切地说它实际上是Cocoa SDK)使用引用计数或所有权的机制。

你可能已经知道它是如何工作的,但你还需要知道,在Cocoa中,如果一个对象A需要使用另一个对象B,它应该拥有(即保留)它。对象A不应该依赖于其他对象C已经保留了B,因为它不知道C什么时候释放它。在你的例子中,因为NSArray需要使用在它生命周期中添加到它的所有对象,它需要保留所有对象。因此,当数组被取消分配时,它需要释放它们。

当你处理大量对象时,"你需要保留你以后要用的东西"这个概念是非常重要的。

在apple开发指南中有几个地方解释了如果您打算以后使用它,那么获取对象的所有权(发送保留消息)是一个很好的实践。你应该这样做,这样当你仍然需要访问对象时,对象就不会被销毁。

考虑到这一点,你是正确的假设NSArray保留对象时,它被添加到集合,因为它仍然可能试图访问它之后。

您可以查看内存管理编程指南

当你向集合(如数组、字典或集合)中添加对象时,该集合获得该对象的所有权。

http://developer.apple.com/library/mac/文档/可可/概念/MemoryMgmt/文章/mmPractical.html #//apple_ref/doc/uid/TP40004447-SW3

或集合编程主题获取更多详细信息

…在托管内存环境中,当对象被添加时,会收到一条retain消息。

http://developer.apple.com/library/mac/文档/可可/概念/收藏/文章/Arrays.html #//apple_ref/doc/uid/20000132 - sw1

  • 第一点你说得对。当一个对象被添加到数组中时,该数组保留该对象。因此,对于先前保留的对象,必须在将其添加到数组后释放它,否则可能会导致内存泄漏。

  • 同样,当对象被删除时从数组中释放对象。所以,如果你想留下它,

  • 当数组被释放时,如您据推测,阵列将释放所有它包含的对象。因此,单独释放每个对象是没有必要,事实上,会的

  • 最后,关于代码行in -viewDidUnload,你引用:

    self.myArray = nil;
    

只要myArray属性按如下方式合成,就可以正确地处理内存管理:

@synthesize myArray;

synthesize创建了一个setter,该setter有效地执行以下操作:

- (void)setMyArray(NSMutableArray *)anArray
{
    if (![myArray isEqual:anArray]) {
        [myArray release];
        myArray = anArray;
        [myArray retain];
    }
}

因此,当调用上述setter时,将首先释放旧数组(只要它不是与新数组相同的对象)。然后,它将保留新数组,在本例中为nil。请注意,保留nil不会做任何事情,也不会触发错误。

当然,如果你不合成myArray属性,或者如果你重写setter,你就会有内存问题,除非你也释放旧的值&在setter中保留new

最新更新