字符串形成是由编译器优化的吗?

时间:2009-08-24 02:04:36

标签: objective-c cocoa compiler-construction

我试图回答关于==运算符的另一个问题,我创建了这段代码:

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

这里有一些编译技巧吗?

4 个答案:

答案 0 :(得分:6)

显然正在进行字符串统一,至少在单个编译单元中。我建议您通过man gcc进行简短的访问,在此期间您将访问“string”的所有用法。您会找到一些与文字NSString及其免费桥接对应项CFString s:直接相关的选项:

  • -fconstant-string-class = class-name 设置用于实例化@"..."文字的类的名称。除非您使用GNU运行时,否则默认为NSConstantString。 (如果你不知道你是不是,你就不是。)
  • -fconstant-cfstrings 允许您在撰写CFString时使用内置内容创建CFSTR(...)

您可以使用-fwritable-strings禁用C字符串文字的uniquing,但不推荐使用此选项。我无法想出能够阻止在Objective-C文件中单独使用NSString文字的选项组合。 (任何人都想与Pascal字符串文字对话?)

您看到-fconstant-cfstringsCFString.h对用于创建CFSTR()文字的CFString宏的定义中发挥作用:

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

如果你看一下CFString.c中非内置__CFStringMakeConstantString()的实现,你会发现该函数确实使用非常大的CFMutableDictionary执行了无条件:

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

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

答案 1 :(得分:4)

NSString被定义为不可变类型,因此只要编译器可以通过组合相同的字符串来优化事物,它就应该。正如您的代码演示的那样,gcc显然会针对简单情况执行此优化。

答案 2 :(得分:2)

对于cString和aString,C,C ++和Objective C编译器可以重用编译时字符串对象(如果它在多个位置声明)。

答案 3 :(得分:0)

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

可能字符存储在内存的静态部分(带代码),NSStrings *指向内存的那一部分。一旦你尝试修改其中一个字符串,它将在其他地方(堆)创建新字符串,然后引用该内存。