NSString内部机制 - 长度是如何工作的?

3

我有一个关于NSString内部的问题。

我想检查一个字符串的长度,基本上我想知道一个NSString是否每次都知道它的长度/计数/计数并缓存结果。

我应该存储它的长度并计算,还是每次调用长度方法?

为了测试一个字符串,我可以测试是否为空,或者询问它的长度。

if (str != nil) {
  // compute
}

if ([str length]) {
  // compute
}

哪一个是最快的? 哪一个更节省内存?

谢谢。

5个回答

8
检查是否为nil("没有对象")绝对不同于向(NSString)对象发送length消息。只有一个条件检查是有效的,可以测试是否为“空”字符串。 (“空”字符串是一个对象,因此不是nil。)
更重要的问题是:NSString是否存储长度,还是类似于“正常c字符串”的哨兵终止? NSString将长度存储为内部属性,因此length是O(1)操作。
祝愉快编码。

7

CFStringGetLength函数的工作原理如下:

(来自http://opensource.apple.com/source/CF/CF-550.43/CFString.c)

/* Returns length; use __CFStrLength2 if contents buffer pointer has already been computed.
*/
CF_INLINE CFIndex __CFStrLength(CFStringRef str) {
    if (__CFStrHasExplicitLength(str)) {
        if (__CFStrIsInline(str)) {
                return str->variants.inline1.length;
        } else {
                return str->variants.notInlineImmutable1.length;
        }
    } else {
        return (CFIndex)(*((uint8_t *)__CFStrContents(str)));
    }
}

所以对于所有情况,它应该是O(1)。

3

以下两种方法——测试 NSString 指针是否为 nil 和测试 NSString 的长度 —— 它们并不等价。一个长度为零的 NSString 对象是存在的,而指向它的指针并不等于 nil。

据我所知(如果发现我是错的,我会很惊讶),NSString 的长度存储在对象内部作为高效引用的属性。缓存长度通常是不必要的复杂性。


1

NSString是不可变类,因此长度始终保持不变。


一个 NSMutableString 是否也将其长度存储为 O(1) 属性? - Chris Gregg
我认为(因为它更有效率),但我不确定。 - MByD

1
补充说明:针对[string length]的测试在两种情况下都会评估为0/nil/NO(即字符串为nil和字符串长度为零)。

这让我想起来:作为一个既有Java背景又有Smalltalk背景的人,我一直很好奇nil到底是什么。它是一个特殊的类(就像在Smalltalk中没有原语,一切都是对象),还是只是一个等同于int 0的常量?我想由于C语言的根源,0、nil、NULL、NO、false都是相同的-0? - fzwo
1
nilobjc.h 中被定义为 __DARWIN_NULL,而 __DARWIN_NULL 在 <sys/_types.h> 中被定义为 ((void *)0) - jscs
3
nilnull是代表“无对象”的特殊值。nil是对应“无类型”的唯一取值:即使在实现细节泄露的情况下(比如"0/NULL"),也可以将其视为这样的值。也就是说,nil是一个仅能表示“无对象”的值。NULL vs nil 可能会引起兴趣,因为它表明Objective-C实际上只是在C/C++之上的一个层面。[我上面所说的基于语义的使用。] - user166390

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接