为什么 Swift 身份运算符 \\”===\\” 为 NSNumbers 返回 true?

Why does the Swift identity operator "===" return true for NSNumbers?

运算符"==="应该比较类引用以确定双方是否引用同一个对象:

1
2
3
4
5
var objectA : NSNumber = 1
var objectB : NSNumber = 1

print(objectA === objectB)
// return true,

所以我的问题是 NSNumber 将对象package成同一个对象,这样做的后端逻辑如何。


NSNumber 是少数几个有时可以表示为标记指针的类之一(至少在 Apple 平台上;我认为这不适用于 (Core)Foundation 的开源版本)。

基本上,这意味着 NSNumber 不是指向位于内存中其他位置的类的实际实例的指针,而是将其值(在本例中为 1)直接存储在指针内。你可以自己看看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import Foundation

let x: NSNumber = 1
let y: NSNumber = 2

// Tagged pointers: the number is stored inside the pointer representation.
print(Unmanaged.passUnretained(x).toOpaque())  // 0x0000000000000137
print(Unmanaged.passUnretained(y).toOpaque())  // 0x0000000000000237

class C {}
let c = C()

// Not a tagged pointer; just a regular pointer to allocated memory.
print(Unmanaged.passUnretained(c).toOpaque())  // 0x00007fb32276daa0

同样的优化也可以应用于 NSString 和其他类型。有关更多详细信息,请阅读 Mike Ash 出色的深度博文:

  • 周五问