esi*_*gel 1 memory-management objective-c
我正在阅读关于内存管理的苹果文档,并遇到了一些我不明白的内容.基本上,我不明白为什么不需要通过"getter"方法保留实例变量.我写了这个小程序,看看会发生什么.我以为会有崩溃,但我显然错过了一些东西.
// main.m
// Test
//
#import <Foundation/Foundation.h>
#import "Test.h"
int main(int argc, char *argv[])
{
NSAutoreleasePool *p = [[NSAutoreleasePool alloc] init];
//Initialize the test object
Test *t = [[Test alloc] init];
//Set the value to 5
[t setMyNum:[NSNumber numberWithInt:5]];
//Save a temp number that points to the original number
NSNumber *tempNum = [t myNum];
//release old number and retain new
[t setMyNum:[NSNumber numberWithInt:7]];
//Shouldn't this crash because tempNum is pointing to a deallocated NSNumber???
NSLog(@"the number is %@",tempNum);
[p drain];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
tempNum不指向解除分配的对象吗?
所有帮助表示赞赏.
编辑这是getter和setter方法中的代码
#import "Test.h"
@implementation Test
- (void)setMyNum:(NSNumber *)newNum {
[newNum retain];
[myNum release];
myNum = newNum;
}
-(NSNumber *)myNum {
return myNum;
}
@end
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我正在调用旧对象上的release.
编辑有人建议,我认为这是正确的,因为tempNum仍然存在的原因是因为它尚未从池中自动释放.但即使在NSLog消息之前将[pool drain]移动到右边,也没有崩溃??? 奇怪的.
由于您没有显式释放任何对象,因此在允许自动释放池耗尽之前不会释放任何内容.尝试[p drain]在最后一次NSLog通话前插入.它应该崩溃NSLog调用.
此外,如果您没有在setMyNum:方法中保留NSNumber,您会发现如果[p drain]在分配tempNum之前添加它将会崩溃.
为了澄清原始问题,调用getter方法不会(也不应该)必然意味着调用者想要获取所有权(即保留)变量.如果是这种情况,此代码将泄漏:
NSLog("Number is %@", [t myNum]);
Run Code Online (Sandbox Code Playgroud)
此外,NSNumber似乎有一个优化,对于小数字,它们缓存NSNumber对象,保留额外的副本,并返回该版本.因此对于小常量,[NSNumber numberWithInt: N]将返回具有2个引用计数的对象(可通过[theNumber retainCount]).要明确地看到会发生什么,在程序中使用一个更大的常量,NSNumber将保留一个引用计数为1的"新鲜"对象(也将自动释放).