您将 retainCount 作为有符号整数打印,而实际上它是无符号整数(NSUInteger
格式说明符为%u
, not的类型%d
)。-1 等价于UINT_MAX
,表示对象没有retainCount。很可能 NSString 已经认识到给定的字符串是不可变的,并将指针分配给静态的 @"" 空 NSString,而不是在堆上放置一个。
实际上,您可以使用以下代码来确认这一点:
NSString* str1 = [[NSString alloc] initWithFormat:@""];
NSString* str2 = [[NSString alloc] initWithFormat:@""];
NSLog(@"string1: %p, string2: %p", str1, str2);
上面的代码应该为 str1 和 str2 打印相同的指针地址,证实了我的理论,即 NSString 优化了这个特殊情况,确实如此:
06:46:30.142 StringTest[45214:303] string1: 0x7fff7d8acf90, string2: 0x7fff7d8acf90
所以让我们看看这是否特定于 NSString。应该是这样,否则所有初始化为空字符串的 NSMutableString 对象都将指向同一个内存!
NSMutableString* str1 = [[NSMutableString alloc] initWithFormat:@""];
NSMutableString* str2 = [[NSMutableString alloc] initWithFormat:@""];
NSLog(@"string1: %p, string2: %p", str1, str2);
输出:
06:53:36.688 StringTest[45278:303] string1: 0x10010a850, string2: 0x10010a890
两个不同的内存位置。这样就完成了,Foundation 框架中的一个巧妙的小优化。TIL
编辑:
正如 bbum指出的那样,你永远不应该依赖 retainCount,这是一个例子,如果你这样做,事情可能会出错