2009-08-24 68 views
4

我试图回答关于==操作符的另一个问题,我创造了这个代码:编译器是否优化了字符串的形成?

NSString *aString = @"Hello"; 
NSString *bString = aString; 
NSString *cString = @"Hello"; 

if (aString == bString) 
    NSLog(@"CHECK 1"); 

if (bString == cString) 
    NSLog(@"CHECK 2"); 

if ([aString isEqual:bString]) 
    NSLog(@"CHECK 3"); 

if ([aString isEqual:cString]) 
    NSLog(@"CHECK 4"); 

NSLog(@"%i", aString); 
NSLog(@"%i", bString); 
NSLog(@"%i", cString); 

却惊讶的结果:

Equal[6599:10b] CHECK 1 
Equal[6599:10b] CHECK 2 
Equal[6599:10b] CHECK 3 
Equal[6599:10b] CHECK 4 
Equal[6599:10b] 8240 
Equal[6599:10b] 8240 
Equal[6599:10b] 8240 

是有一些编译器弄虚作假回事?

回答

6

显然有字符串uniquing继续,至少内的单个编译单元。我建议您通过man gcc进行简要介绍,在此期间您将访问“字符串”的所有用途。你会发现,对文字NSString S和他们的免费电话桥接的同行,CFString小号直接相关的几个选项:

  • -fconstant-string-class = 类名设置用于类的名称实例化@"..."文字。它默认为NSConstantString,除非您使用的是GNU运行时。 (如果你不知道,如果你是,你是不是。)
  • -fconstant-cfstrings中能够使用内置的,当你写CFSTR(...)创建CFString秒。

虽然不推荐使用此选项,但可以使用-fwritable-strings禁用C字符串文字的取消定位。我无法想出一个可以阻止在Objective-C文件中排除NSString文字的选项组合。 (任何人都想找帕斯卡尔字符串文字?)

你看-fconstant-cfstrings进入中使用的CFSTR()CFString.h的定义发挥创造CFString文字:如果你看的实施

#ifdef __CONSTANT_CFSTRINGS__ 
    #define CFSTR(cStr) ((CFStringRef) __builtin___CFStringMakeConstantString ("" cStr "")) 
    #else 
    #define CFSTR(cStr) __CFStringMakeConstantString("" cStr "") 
    #endif 

CFString.c非内置__CFStringMakeConstantString(),你会看到该功能确实执行uniquing使用非常大的CFMutableDictionary

if ((result = (CFStringRef)CFDictionaryGetValue(constantStringTable, cStr))) { 
     __CFSpinUnlock(&_CFSTRLock); 
    } 
    // . . . 
    return result; 

另请参阅对问题的回答,"What's the difference between a string constant and a string literal?"

+0

+1优秀的答案,jayw。 – 2009-08-24 17:53:54

2

如果在不止一个位置声明为井和CSTRING ASTRING,C,C++,和目标C编译器可以重复使用一个编译时间字符串对象。

4

的NSString被定义为一个不可变型,所以每当编译器可通过组合相同的字符串优化的东西,它应该。正如你的代码演示的那样,gcc显然会为简单的情况执行这种优化。

+0

这是正确的。字符串的内部类型实际上是一个NSConstantString,它不能被释放。编译器将它变成静态的,显然将它的-release方法重写为no-op。 – 2009-08-24 03:56:31

0

也许简单的写入时复制优化?由于所有3个字符串都指向相同的“字符集”,因此在修改其中一个字符串之前,创建单独的副本没有意义。

大概字符被存储在存储器的静态部分(用代码)和NSString的*指向的存储器的部分。一旦你尝试修改其中一个字符串,它会在其他地方创建新的字符串(堆),然后引用该内存。

+0

您不能修改NSString。 – 2009-08-24 06:32:21

+0

没错,我在想概念上更多...无论如何,他们似乎都指向相同的记忆部分,因为他们代表了同一组字符... – stefanB 2009-08-25 07:04:34