编译器是否优化了字符串形成?

问题描述 投票:0回答: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

这里是否存在一些编译器欺骗?

objective-c cocoa compiler-optimization
4个回答
6
投票

至少在单个编译单元内,明显存在字符串唯一性。我建议您简单浏览一下

man gcc
,在此期间您可以了解“字符串”的所有用法。您会发现一些与文字
NSString
及其免费桥接对应项
CFString
s:

直接相关的选项
  • -fconstant-string-class
    =class-name
    设置用于实例化
    @"..."
    文字的类的名称。除非您使用 GNU 运行时,否则它默认为
    NSConstantString
    。 (如果你不知道自己是不是,那么你就不是。)
  • -fconstant-cfstrings
    允许在您编写
    CFString
    时使用内置函数来创建
    CFSTR(...)

您可以使用

-fwritable-strings
禁用 C 字符串文字的唯一性,尽管此选项已弃用。我无法想出一个选项组合来阻止 Objective-C 文件中
NSString
文字的唯一性。 (有人想与 Pascal 字符串文字交谈吗?)

您会看到

-fconstant-cfstrings
CFString.h
用于创建
CFSTR()
文字的
CFString
宏的定义中发挥作用:

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

如果您查看

__CFStringMakeConstantString()
 中非内置 
CFString.c
的实现,您会发现该函数确实使用非常大的
CFMutableDictionary
来执行唯一性:

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

另请参阅对问题的回答,“字符串常量和字符串文字有什么区别?”


4
投票

NSString 被定义为不可变类型,因此每当编译器可以通过组合相同的字符串来优化事物时,它就应该这样做。正如您的代码所示,gcc 显然确实针对简单情况执行了这种优化。


2
投票

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


0
投票

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

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

© www.soinside.com 2019 - 2024. All rights reserved.