@""和@"123"之间有什么不同?

exp*_*xpl 0 objective-c ios

当我测试方法"retainCount"时,我遇到了一个问题,如下所示:

NSString *s_afmt0 = [[NSString alloc] initWithFormat:@""]; //-1
NSString *s_afmt1 = [[NSString alloc] initWithFormat:@"123"]; //1
NSLog(@"s_afmt0:%d", [s_afmt0 retainCount]);
NSLog(@"s_afmt1:%d", [s_afmt1 retainCount]);
Run Code Online (Sandbox Code Playgroud)

结果:s_autf0:-1 s_autf1:1我不知道为什么?为什么s_afmt0的retainCount为-1​​,而s_autf1的retainCount为1.为什么@""和@"123"之间有什么区别?谁能解释一下?谢谢

yfr*_*cis 9

你将retainCount打印为有符号整数,实际上它是一个无符号整数(NSUInteger格式说明符为的类型%u,不是%d).-1相当于UINT_MAX,表示该对象没有retainCount.很可能NSString已经认识到给定的字符串是不可变的,并且指定了指向静态@""空NSString的指针,而不是将其放在堆上.

实际上,您可以使用以下代码进行确认:

NSString* str1 = [[NSString alloc] initWithFormat:@""];
NSString* str2 = [[NSString alloc] initWithFormat:@""];

NSLog(@"string1: %p, string2: %p", str1, str2);
Run Code Online (Sandbox Code Playgroud)

上面的代码应该为str1和str2打印相同的指针地址,这证实了我的理论,即NSString优化了这个特定的情况,实际上它确实:

06:46:30.142 StringTest[45214:303] string1: 0x7fff7d8acf90, string2: 0x7fff7d8acf90
Run Code Online (Sandbox Code Playgroud)

所以让我们看看这是否特定于NSString.它应该是,否则所有初始化为空字符串的NSMutableString对象都将指向相同的内存!

NSMutableString* str1 = [[NSMutableString alloc] initWithFormat:@""];
NSMutableString* str2 = [[NSMutableString alloc] initWithFormat:@""];

NSLog(@"string1: %p, string2: %p", str1, str2);
Run Code Online (Sandbox Code Playgroud)

输出:

06:53:36.688 StringTest[45278:303] string1: 0x10010a850, string2: 0x10010a890
Run Code Online (Sandbox Code Playgroud)

两个不同的内存位置.所以你有它,在Foundation框架中进行了一个简洁的小优化.TIL

编辑:

正如bbum 指出的那样,你永远不应该依赖retainCount,这是一个例子,如果你做的事情可能会出错

  • bbum我会说,如果你限制你的调试和生产选项.但是,你自己做了一些使用retainCount的实验,并在博客上写了一篇关于它的内容,所以如果你所做的只是黑客攻击,我认为很棒的实验和学习你对平台的了解 (2认同)