Objective-C中设置nil和释放(releasing)的区别

29

我了解到在dealloc中你需要执行 [object release]; 但是在viewDidUnload(在UIViewController子类中)中你需要执行self.object = nil。两者有何不同呢?因为self.object = nil(假设object是(nonatomic, retain)属性)会保留nil(什么也不做),然后释放旧值,引用计数就变成0了,那么这到底有什么区别吗?

4个回答

55

self.object = nil 调用了你的setter方法,该方法将释放旧值,将成员设置为 nil,并可能执行其他操作(因为它是一个方法,所以它可以做任何事情)。其中“任何事情”的部分潜在地很危险;例如,请参见此问题

[object release] 释放旧值,但是将成员留下作为现在悬空指针,这是引起错误的好方法。在 dealloc 中,它并不真的重要,因为指针本身也即将消失,但在任何其他情况下,释放成员而不将其设置为 nil 是一个非常糟糕的想法。

(另外,你永远不应该假设释放对象会使其引用计数为0. 它会释放你的引用,但是其他对象仍然可能持有对它的引用。)


4
请注意,苹果公司明确建议在初始化和释放函数中不要使用设置器/获取器(有充分的理由),因此在dealloc中使用[object release] - 这不仅仅是“在dealloc中并不重要”,实际上在dealloc中是推荐的方式。 - Peter N Lewis
没错,我的意思是拥有一个非nil指针并不重要(也就是说,在dealloc中释放后你不需要再将object=nil)。 - smorgan
1
实际上,使用合成的ivars时,在dealloc中必须使用setter。请参阅http://developer.apple.com/iphone/library/documentation/cocoa/Conceptual/ObjectiveC/Articles/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW1搜索短语“synthesizing the instance variable”。 - ustun
@ustun,这并不一定是正确的。您可以使用合成的ivars并使用声明进行合成,例如:@synthesize myIvar = _myIvar; 然后在dealloc中使用[_myIvar release]; - tbehunin
3
请注意,[myivar release]实际上没有使用setter方法,而是使用了支持self.myivar的实例变量。因此,在dealloc中使用[myivar release]myivar = nil是完全可以的。然而,使用self.myivar = nil就不行。 - memmons

6
如果你执行 object = nil 而没有执行 [object release],那可能会导致内存泄漏。如果你执行[object release]而没有在之后执行 object = nil,那么对象就会变成 @Jim 所建议的悬空指针。self.object = nil 是调用setter函数的简写形式。

1

如果你只是释放一个对象,那么它将变成自由对象。

如果你试图对已释放的对象执行任何操作,那么你的应用程序就会崩溃。为了避免这种事故,最好在释放对象后将其“分配给nil”。因为我们都知道,在nil上执行的任何操作都不会被执行 :)


1
如果你执行 [object release],并且想要访问该对象,应用程序会崩溃。如果你执行 object = nil,并且想要访问该对象,什么也不会发生。
原因在于 [object release] 中,你试图释放该对象。因此它没有任何指针(没有内存)。在 object = nil 中,你试图将对象赋值为空指针。所以如果你尝试访问该对象,什么也不会发生。
通常我们将代码编写为 [object release]; object = nil;,因为如果意外访问该对象,应用程序不会崩溃。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接