根据以下代码,请提供建议
NSString *str= [[NSString alloc] initWithString:@"Hello world"];
NSLog(@"Length: %lu\n", [str length]); // 11
NSLog(@"Retain count is %lu\n", [str retainCount]); //1152921504606846975
[str release];
NSLog(@"%lu\n", [str length]); // 11
NSLog(@"Retain count is %lu\n", [str retainCount]); //1152921504606846975
最初我想知道为什么数字这么大但后来看到了post explaining it。让我问这个问题......为什么我使用%d
vs %lu
时这个数字会发生很大变化。最初,我使用%d
,但收到警告说“转换指定类型为int但参数的类型为NSUInteger(也称为unsigned long)。修复是将%d
更改为{{ 1}}“
为什么保留计数不减少? %lu
发送str
为什么我发送release
后仍然可以访问str
?
答案 0 :(得分:8)
这可能是一个难以接受的答案,但这是你应该做的:
可能是因为你以一个常量字符串(@"Hello world"
)开始,当你调用release时内存没有被释放,并且retainCount很大。但是如果你不得不关心retainCount,你做错了。
你正在正确的位置释放字符串,这才是最重要的 - 不要试图在以后使用它。
答案 1 :(得分:0)
最终,行为是由NSString的实现定义的 - 只要在每种情况下正确使用retain / release,你就会安全。
可能发生的事情:NSString文字是不朽的。你可以写while (1) { [@"String" release]; }
而且没有问题。
您调用的副本可能会返回指向字符串文字的指针。在伪代码中:
- (id)initWithString:(NSString *)str
{
self = [super init];
if (self != nil) {
if ([str _isStringLiteral] || [str _isImmutable]) {
[self release];
return [str retain];
}
...
}
在这种情况下,当您通过[[NSString alloc] initWithString:stringLiteral]
时,会返回指向字符串文字的指针。因为将release
发送到不朽的字符串文字什么都不做,你可以看到为什么它仍然是一个有效的对象,你可以认为它是一个已发布的对象。
永远不要依赖这些细节/优化,只需使用正常的生命周期并重新计算,你就可以了。