编译器是聪明的,而不是创建几十个不同的 NSString 实例,它们都持有相同的值,他创建了一个无法释放的实例,而所有其他实例只是指向在你的程序中硬编码的 NSString。
而且因为硬编码的 NSString 永远不会被释放,即使在自动释放池释放它之后,你也可以使用它。
这只是涵盖了您错误的内存管理。你绝对不应该依赖这种行为。
编辑。没什么好说的了。您使用 stringWithString:literal 创建的 NSString 将简单地指向文本在内存中的位置。
一个小例子:
NSString *string = @"Foo";
NSLog(@"%@ - %p", string, string);
NSString *string2 = string;
NSLog(@"%@ - %p", string2, string2);
NSString *string3 = [string copy];
NSLog(@"%@ - %p", string3, string3);
NSString *string4 = [string retain];
NSLog(@"%@ - %p", string4, string4);
NSString *string5 = [NSString stringWithString:string];
NSLog(@"%@ - %p", string5, string5);
NSString *string6 = [[NSString alloc] initWithString:string];
NSLog(@"%@ - %p", string6, string6);
你会看到它们都指向同一个地址。
2011-02-22 13:24:41.202 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.204 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.204 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.206 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.206 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.207 xxx[40783:207] Foo - 0x74120
而且它们都永远不会被释放。因此,您可以从代码中的其他方法访问 string5,它仍然指向地址 295740,并且 NSString "Foo" 仍然存在。
但是此时将释放不指向字符串文字的 NSString 对象,并且您将获得错误的访问异常。
您违反了内存管理规则,但如果您只使用字符串文字,您将永远不会注意到它。直到编译器的行为发生变化。
所以做对了,学习正确的内存管理,不要依赖内部。如果您以后需要它们,请保留所有自动释放的对象。即使它们指向字符串文字