Objective c NSString-stringWithFormat与stringWithString

Objective c NSString-stringWithFormat与stringWithString,objective-c,string,nsstring,stringwithformat,Objective C,String,Nsstring,Stringwithformat,我在一个.m文件中声明了一个全局NSString变量。当我使用stringWithFormat在.m文件中的任何位置给它一个字符串值时,该值不会在函数调用之间保持。但是,当我使用stringWithString执行相同的操作时,该值会在整个实现和任何函数调用中保持不变,从而使其具有真正的全局行为。换言之,stringWithFormat和stringWithString的内存管理在内部有什么不同 为什么在使用stringWithFormat时,stringWithString的值在抛出“发送到解

我在一个.m文件中声明了一个全局NSString变量。当我使用stringWithFormat在.m文件中的任何位置给它一个字符串值时,该值不会在函数调用之间保持。但是,当我使用stringWithString执行相同的操作时,该值会在整个实现和任何函数调用中保持不变,从而使其具有真正的全局行为。换言之,stringWithFormat和stringWithString的内存管理在内部有什么不同

为什么在使用stringWithFormat时,stringWithString的值在抛出“发送到解除分配实例的消息”(在随后使用NSString时,例如在另一个函数中的NSLog语句中,该函数在使用stringWithFormat为NSString提供值的函数之后)时仍然存在?当我用stringWithString替换它时,没有这样的问题

谢谢


编辑:我忘了提到是的,当我在之后做手动保留时,它在stringWithFormat的情况下工作。该值持续存在。因此,问题就来了。

编译器很聪明,他没有创建几十个不同的NSString实例,这些实例都具有相同的值,而是创建了一个无法释放的实例,而所有其他实例都指向程序中硬编码的NSString

因为硬编码的NSString永远不会被释放,所以即使在自动释放池释放它之后,您也可以使用它

这只是掩盖了错误的内存管理。你绝对不应该依赖这种行为


编辑。没什么好说的了。使用stringWithString:literal创建的NSString将简单地指向内存中的literal位置

举个小例子:

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对象,并且您将获得错误的访问异常

您违反了内存管理规则,但如果只使用字符串文字,您将永远不会注意到这一点。直到编译器的行为改变


所以正确地做,学会正确的内存管理,不要依赖于内部。如果以后需要,请保留所有自动释放的对象。即使它们指向字符串文本

,编译器也很聪明,它不会创建几十个不同的NSString实例,所有这些实例都具有相同的值,而是创建一个无法释放的实例,而所有其他实例只指向程序中硬编码的NSString

因为硬编码的NSString永远不会被释放,所以即使在自动释放池释放它之后,您也可以使用它

这只是掩盖了错误的内存管理。你绝对不应该依赖这种行为


编辑。没什么好说的了。使用stringWithString:literal创建的NSString将简单地指向内存中的literal位置

举个小例子:

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对象,并且您将获得错误的访问异常

您违反了内存管理规则,但如果只使用字符串文字,您将永远不会注意到这一点。直到编译器的行为改变


所以正确地做,学会正确的内存管理,不要依赖于内部。如果以后需要,请保留所有自动释放的对象。即使它们指向字符串文本

,听起来似乎您没有保留该字符串,因此,当您稍后尝试访问它时,它已被解除分配。如果你不熟悉内存管理,可以看看苹果的

-stringWithString:
没有中断的原因很可能是因为编译器正在对字符串文本进行一些优化;它查看整个程序并只存储对定义的相同字符串的一个引用。因此,您的指针将在应用程序的整个生命周期内保持有效


你不应该依赖这个。您不能保证所有编译器都会进行此优化。在创建变量时保留它,在不再需要时释放它。

听起来好像您没有保留字符串,因此,当您稍后尝试访问它时,它已被释放。如果你不熟悉内存管理,可以看看苹果的

-stringWithString:
没有中断的原因很可能是因为编译器正在对字符串文本进行一些优化;它查看整个程序并只存储对定义的相同字符串的一个引用。因此,您的指针将在应用程序的整个生命周期内保持有效


你不应该依赖这个。您不能保证所有编译器都会进行此优化。制作变量时保留它,停止使用时释放它。

请粘贴一些代码。这是一个理论问题。我看到NSString有两种情况,我只是想知道stringWithFormat和stringWithStringPlease之间的区别,粘贴一些代码。这是一个理论问题。我看到NSString有两种情况,我只想知道stringWithFormat和StringWithString在文章中的区别。我确实弄明白了很多。在使用stringWithFormat为字符串指定一个值之后,我确实对它执行了保留操作,没有任何问题。而stringWithString不需要采取这样的操作