NSString *s1 = @"string1";
// NSString *s2 = [[NSString alloc]stringWithFormat:@"string2"];
NSString *s2 = [[NSString alloc] initWithFormat:@"string2"];
我知道这是非常基本的概念,但我并不是100%清楚这一点。
第一个没有分配内存地址,发送一个分配内存地址...... 第二个增加变量的引用计数但不增加第一个... 即使我理解这个概念,但是当我应该使用第一个或第二个时,我不知道这种情况。
我什么时候应该使用第一个?还应该什么时候用于第二个?
提前致谢..
答案 0 :(得分: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
,s2
和s3
都指向同一个字符串实例,而s4
最终成为新实例。这是因为NSString
检测字符串何时从常量字符串初始化,并且当完全有效时,返回常量字符串而不是费心分配新的内存块来保存相同的内容。 stringWithFormat:
案例的优化程度不是很高,因为所有潜在的格式字符串处理都会使得这样的优化对于实现都没有实际意义,而且可能是不自然的。
换句话说, not 只是通过代码检查或指针比较来假设两个字符串相同或不同。使用isEqual:
或更好的isEqualToString:
。
答案 1 :(得分:4)
你永远不应该使用第二个 - +stringWithFormat:
是一个类方法。包括你的第一个例子,你基本上有3个选择:
NSString *s1 = @"string1";
NSString *s2 = [[NSString alloc] initWithString:@"string2"];
NSString *s3 = [NSString stringWithFormat:@"string3"];
在这种情况下, s1
是一个指向常量字符串的指针。 s2
和s3
都指向您已创建的新字符串,但已为您保留s2
,s3
已自动释放。如果您只需要一个临时对象,则自动释放的对象s3
或常量对象s1
是不错的选择。如果你需要保持字符串,你应该使用s2
(实际上现在我想到它s1
也会在这种情况下起作用 - 尽管如此,它并不是真正的惯用语。
您可以向s1
发送s3
消息,使s2
或retain
等同于s2
。您也可以通过发送autorelease
消息将{{1}}转换为等效对象。
答案 2 :(得分:1)
正如您所指出的那样,字符串文字如@"string1"
(或第二行的@"string2"
)不是分配。该字符串实际上作为常量存储在可执行文件的数据部分中,就像您声明的任何常量一样。以这种方式创建的字符串实际上没有引用计数;您可以向他们发送-retain
和-release
条消息,但不会发生任何事情。
你的第二行是不正确的; +stringWithFormat:
实际上是一个类方法,如果没有任何格式参数,使用+stringWithFormat:
并没有意义。通常,如果您没有特定的理由使用其他表单,只需使用字符串文字形式。如果在应用程序周围已经存在常量对象,则无需分配新对象。
答案 3 :(得分:1)
如果您要将常量字符串传递给它,请不要使用任何...WithFormat:
方法。无需为简单的案例解析格式字符串。