[英]Objective-C memory model
我试图将我的头缠在Objective-C内存模型的一部分上(特别是在iPhone上,因此没有GC)。 我的背景是C / C ++ / Java,下面的代码存在问题(也想知道我是否以“ Objective-C方式”执行此操作):
- (NSSet *) retrieve
{
NSMutableSet *set;
set = [NSMutableSet new];
// would normally fill the set in here with some data
return ([set autorelease]);
}
- (void) test
{
NSSet *setA;
NSSet *setB;
setA = [self retrieve];
setB = [[self retrieve] retain];
[setA release];
[setB release];
}
开始编辑
根据以下注释,更新了检索方法:
- (NSSet *) retrieve
{
NSMutableSet *set;
set = [[[NSMutableSet alloc] initWithCapacity:100] autorelease];
// would normally fill the set in here with some data
return (set);
}
结束编辑
上面的代码为[setA release]提供了警告“调用者此时不拥有对象引用计数的不正确减少”。
我虽然说“ new”将引用计数设置为1,但是“ retain”调用将添加1,而“ release”调用会将其删除1。给定的情况是setA的引用计数不会为0。 end和setB的引用计数最终是否为1?
根据我的尝试和发现,setB是正确的,并且没有内存泄漏,但是我想了解为什么会这样(我对“ new”,“ autorelease”的理解有什么问题, “保留”和“释放”)。
我虽然说“ new”将引用计数设置为1,但是“ retain”调用将添加1,而“ release”调用会将其删除1。给定的情况是setA的引用计数不会为0。 end和setB的引用计数最终是否为1?
您将autorelease
。 当-(void)test
得到一个集合时,它的保留计数为0。您没有保留setA
,因此当您尝试释放它时,它的保留计数已经为0,因此会出现错误消息。
内存管理的基本规则非常简单:对alloc
, new
和copy*
的调用必须通过对release
/ autorelease
调用来平衡。 前者取得所有权,后者放弃所有权。
唯一棘手的部分是在处理共享库时 ,您不拥有对象的所有权,因此在您获得对它的引用与使用之间,它可能会被丢弃。 这有一个简单的解决方案:如有疑问,请保留它。
通过在许多情况下使用属性 ,可以使事情变得更加简单。
不要以绝对数字来思考。 那可能是非常具有欺骗性的。 如果您必须有一个数字,则将保留和释放视为增量-在这种情况下, autorelease
已使new
平衡(+1增量和-1增量),因此该方法可以正确地管理其内存,而接收方则不会需要做任何事情,除非它想让对象保持更长的时间。
一定要阅读内存管理文档 。 确实很简单,只需遵循此处描述的规则。 这是一个非常简单的所有权合同,当您希望对象随处可见时,您可以主张所有权;而当您不再关心对象时,则放弃所有权。 在上述情况下,您在retrieve
方法中放弃了所有权,因此,在没有所有权时尝试放弃所有权显然是一个错误。
正如探查器消息提示的那样,您应该考虑所有权。 如内存管理规则中所述 ,每当您拥有使用+alloc
, +new
, -copy
或-mutableCopy
创建的对象时,便拥有该对象并最终负责释放它。 (实际上, +new
只是[[MyClass alloc] init]
简写。)
-retain
接受一个您最初不拥有的对象,并使您拥有它。
-release
获取您拥有的对象并释放其所有权。
-autorelease
获取您拥有的对象并释放其所有权, 但也保证该对象至少存在一点时间 。
您的-retrieve
方法不会转移它返回的对象的所有权。 很好-它遵循内存管理规则(该方法不是+alloc
, +new
, -copy
或-mutableCopy
)。 因此,在不使用-retain
情况下使用-release
是错误的。 只要对象具有临时生存期,不保留或释放-retrieve
的结果同样有效—您的-autorelease
保证对象的临时存在。
http://www.macresearch.org/difference-between-alloc-init-and-new
你可能想要
NSMutableSet *set = [[NSMutableSet alloc] initWithCapacity: someNumber];
要么
NSMutableSet *set = [NSMutableSet setWithCapacity: someNumber];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.