2011-03-14 39 views
0
NSString *s1 = @"string1"; 
// NSString *s2 = [[NSString alloc]stringWithFormat:@"string2"]; 
NSString *s2 = [[NSString alloc] initWithFormat:@"string2"]; 

我知道这是非常基本的概念,但我不完全清楚这一点。目标C,NSSting与“alloc”并且没有“alloc”的区别

第一个不分配的内存地址,并发送一个分配的内存地址... 另外第二个增加了变量的引用计数,但不是第一个...... 尽管我理解这个概念,但不知道当我应该使用第一个或第二个的情况..

什么时候应该使用第一个?还应该什么时候用第二个?

在此先感谢..

+0

根据John的观察来修正你的代码。 – bbum 2011-03-14 05:09:57

回答

4

你不应该使用第二个 - +stringWithFormat:是一个类方法。包括你的第一个例子,你已经基本上3种选择:

NSString *s1 = @"string1"; 
NSString *s2 = [[NSString alloc] initWithString:@"string2"]; 
NSString *s3 = [NSString stringWithFormat:@"string3"]; 

s1在这种情况下是一个指向一个常量字符串。 s2s3都指向您创建的新字符串,但s2已保留给您,并且s3已被自动发布。如果您只需要一个临时对象,则自动释放对象s3或常量对象s1是不错的选择。如果你需要保持字符串,你应该使用s2(实际上,现在我认为它s1也可以在这种情况下工作 - 但它并不真正习惯)。

通过发送retain消息,您可以使s1s3等效于s2。您也可以通过发送autorelease消息将s2转换为等效对象。

+0

非常感谢! – codereviewanskquestions 2011-03-14 04:34:32

1

字符串文字像@"string1"(或第二线的@"string2"),正如你提到的,不分配。字符串实际上是作为常量存储在可执行文件的数据部分中的,就像您声明的任何常量一样。用这种方式创建的字符串并没有真正的引用计数。你可以发送-retain-release消息给他们,没有什么会发生。

你的第二行是不合格的; +stringWithFormat:实际上是一个类方法,如果没有任何格式参数,使用+stringWithFormat:并没有意义。一般来说,只要使用字符串文字形式,如果你没有特定的理由使用另一种形式。如果您的应用程序中已经存在常量对象,则不需要分配新对象。

1

如果您只是要传递一个常量字符串,请不要使用任何...WithFormat:方法。不需要为平凡的情况分析格式字符串。

+1

更不用说它会导致不必要的分配! – bbum 2011-03-14 05:08:23

8

卡尔是对的,但有一些微妙的记住。试想一下:

NSString *s1 = @"string1"; 
NSString *s2 = [[NSString alloc] initWithString:@"string1"]; 
NSString *s3 = [NSString stringWithString:@"string1"]; 
NSString *s4 = [NSString stringWithFormat:@"string1"]; 

NSLog(@"ptrs %p %p %p %p", s1, s2, s3, s4); 

输出是:

ptrs 0x1000010c0 0x1000010c0 0x1000010c0 0x100108da0 

这是正确的; s1,s2s3都指向相同的字符串实例,而s4最终成为新实例。这是因为NSString可检测到字符串正在从一个常量字符串初始化时,并且在完全有效的情况下返回常量字符串而不是分配新的内存块来保存相同的内容。 stringWithFormat:情况可能没有那么优化,因为所有可能的格式字符串处理都使得这样的优化既没有实际意义,也可能不自然。

换句话说,做而不是假设两个字符串只是通过代码检查或指针比较相同或不同。使用isEqual:或更好的是isEqualToString:

+0

+1 @bbum ...很好的说明,谢谢! – 2011-03-14 05:09:00