NSString 引用计数

7

最近我在做一个项目,需要查看字符串的保留计数。

但是它总是返回"2147483647",为什么会这样呢?

请查看以下代码以自行检查。

NSString *str = [[NSString alloc] initWithString:@"Hello World"];
NSLog(@"String Retain Count: %i", [str retainCount]); 

所以我的问题是,为什么它没有像其他对象返回1那样,为什么我得到的是“2147483647”?
提前感谢。

这是一个与https://dev59.com/PUbRa4cB1Zd3GeqPxR0h相同的问题。那里也有一个很好的答案。 - marcc
为什么这是一个社区维基? - Dave DeLong
很抱歉,如果我点击了不该点的地方,在这个网站上还是新手,真的不知道它的含义,非常抱歉。 - itsaboutcode
不用担心,将其设为社区维基是可以的。 - Chuck
然而,忽略有经验的Cocoa程序员的建议并且仅仅使用NSMutableStrings而不是学会正确使用Cocoa是不可取的。 - Chuck
显示剩余2条评论
3个回答

27

编译器比你聪明。

它看到@"Hello world"就会想:“啊哈!一个常量字符串!”

然后它看到[[NSString alloc] initWithString:@"Hello world!"]就会想:“啊哈!使用常量字符串创建了一个不可变对象!”

然后它将这两个内容折叠成一个单一的NSConstantString,它的retainCountUINT_MAX,因此永远无法释放。


2
@itsaboutcode 我建议不要考虑保留计数,而是考虑“我分配了这个字符串,所以我必须释放它”,并让保留计数自行解决。在我写Objective-C的几年中,我想不出一个需要关注保留计数的例子。如果你遵循内存管理规则,就不会有问题。 - Dave DeLong
@ Dave DeLong 这就是我的想法,如果我创建了一个对象:NSString *str = [[NSString alloc] initWithString:@"Hello World"];那么我应该释放它,对吧?但是如果我要释放它,我应该知道它的保留计数是多少?否则,我将向不存在的对象发送消息,结果会导致我的程序崩溃! - itsaboutcode
1
@itsaboutcode 如果你分配了它,就要释放它。没有其他的说法。如果你的代码在释放时崩溃,那么你就做错了。NSMutableString返回1的retainCount的原因恰好是因为它是可变的。它可以被改变,这意味着编译器无法将其优化为常量字符串。 - Dave DeLong
1
@itsaboutcode 忽略RETAINCOUNTS。NSString存在是有原因的:在不需要可变字符串时,请使用它。如果你分配了一个对象,就要释放它。这真的不难... - Dave DeLong
1
保留计数是为计算机而非你自己服务的。你只需关注你所拥有的,并在完成后放弃所有权。将它们合并成单个常量字符串对于你来说有助于节省内存。if (!horse.isAlive) { [self beat: horse]; } - Wevah
显示剩余8条评论

4
NSString *str = [[NSString alloc] initXXX 

通常会分配一些 RAM 并返回一个指针。这个 RAM 将受到释放和保留的影响。但是,当您执行以下操作时:
NSString *str = [[NSString alloc] initWithString:@"Hello World"];

返回的字符串是@"Hello World",因为它是一个字符串常量,已经被分配了。由于它是一个字符串常量,无法释放,因此系统必须将其标记为不可释放。它所做的方式是将其保留计数设置为最大整数值。

NString  *str = [[NSString alloc] initWithFormat:@"Hello World. Today is @%", todayDate];

这个字符串的retainCount为1。虽然其中有一个字符串常量,但它被另一个字符串所附加。由于无法修改该常量字符串,因此会创建“Hello World.”字符串的副本,并将todayDate字符串的内容添加到其中。现在,该内存归调用者所有,其retainCount为1。


2

该字符串在编译时被优化为静态分配的NSString实例,以节省一些变量开销等。您看到如此高的保留计数是因为静态字符串在您所开发的任何平台上都具有最大整数的保留计数。


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