释放操作可能异步工作,这取决于实现。我认为实际上它不是异步的。
但有时框架会额外引用一个实例。而且这个引用可能只在runloop的下一次迭代之后才被释放,或者它可能只有在收到内存警告时才被释放,甚至可能永远不会被释放。在引擎盖下,系统确实试图优化内存操作。例如,字符串文字永远不会被释放,并且您使用这些字符串文字创建的不可变字符串实际上指向相同的字符串文字。但这是一个实现细节,你不能依赖它。
基本上有两条规则:
一旦你将最后一个release 消息发送到一个对象,你就不能访问它。最后,我的意思是从您自己的代码的角度来看。例如:
NSMutableString *str = [[NSMutableString alloc] initWithString:@"Foo"]; // 1 reference from alloc
NSLog("%@", str); // good
[str retain]; // reference count + 1 = 2 total
NSLog("%@", str); // good
[str release]; // reference count - 1 = 1 total
NSLog("%@", str); // good
[str release]; // reference count -1 = 0 total. Object should be considered deallocated
NSLog("%@", str); // bad. It is no longer safe to access the object
如果您发送autorelease,您可以安全地访问该对象,直到您离开自动释放池的当前范围(如果您不使用自己的池,通常直到您从方法返回)。例如:
NSMutableString *str = [[NSMutableString alloc] initWithString:@"Foo"]; // 1 reference from alloc
NSLog("%@", str); // good
[str retain]; // reference count + 1 = 2 total
NSLog("%@", str); // good
[str release]; // reference count - 1 = 1 total
NSLog("%@", str); // good
[str autorelease]; // some time in the future, but after the current runloop iteration: reference count - 1 = 0 total.
NSLog("%@", str); // good. because the object will be released later
而且你不能自动释放比你获取的更多的引用。因为如前所述,自动释放基本上会将release 消息的发送延迟到以后。它会被发送。 autorelease 中的 auto 并不意味着系统会检查对象以查看是否需要释放。
请记住,这些消息被发送到对象,而不是变量。
您的代码:
NSObject * t = [[NSObject alloc] init];
NSObject * t2 = t;
[t release];
[t2 description];
在内存管理方面是这样的:
NSObject * t = [[NSObject alloc] init];
[t release];
[t description];
当您执行此类操作时,您应该发送保留消息并(自动)稍后释放它。我通常使用自动释放。例如:
NSObject * t = [[NSObject alloc] init];
NSObject * t2 = [[t retain] autorelease];
[t release];
[t2 description]; // totally safe to do
或者为了让发生的事情更明显,我们可以将代码分成更多行:
NSObject * t = [[NSObject alloc] init]; // ref = 1
NSObject * t2 = t; // no change in ref count
[t retain]; // ref + 1 = 2
[t autorelease]; // later: ref - 1 = current ref: 2 (-1 scheduled for later)
[t release]; // ref - 1 = 1 (-1 later)
[t2 description]; // totally safe to do because you still have a reference
return;
// end of method
// when the autorelease pool is drained the system sends the scheduled release
// the object is no longer referenced and gets deallocated.
附注:学习这些东西很好,但在生产代码中最好启用 ARC。 ARC 非常稳定、快速,在复杂的应用程序中它会提高您自己代码的稳定性。您必须编写更少的代码,并且必须减少调试。所以帮自己一个忙,在生产中使用 ARC。