2
- (void)showWeakValue
{
    NSString * __weak weakString = [[NSString alloc] initWithFormat:@"First Name: AA"];
    NSNumber * __weak weakNum = [[NSNumber alloc] initWithInt:10];
    NSLog(@"weakString =  %@", weakString);
    NSLog(@"weakNum  = %@",weakNum);
}

输出是

 weakString =  (null)
 weakNum  = 10

为什么weakNum 不为空?因为没有其他强引用weakNum,它应该在分配后立即释放。正确的?

4

2 回答 2

4

我认为要么weakNum立即解除分配(如预期的那样),然后您的代码会调用未定义的行为,要么NSNumber进行棘手的优化,然后您会得到一个始终保持值 10 并且在程序的整个生命周期中都处于活动状态的单例。

编辑:啊哈,呵呵,不。我只是使用记录指针本身

NSLog(@"weakNum pointer: %016llx", (uint64_t)weakNum);

并得到

weakNum pointer: 000000000003e883

现在这很奇怪。不是 16 字节对齐的指向结构的指针?所以这是一个标记的指针

我们来分析指针值!第 0 (LSB) 位已设置,这很清楚 - 表示标记的指针。

第 1 位也已设置:根据链接后面的引用,这是整数的标记对象类。这符合我们的预期。这是第0个半字节。

然后在下一个(第 1 个)半字节中,即第 4...7 位,我们有值 8,它是 binary 100,引用的参考说0100 for 16-bit integers。没错,1000 不适合 8 位,但它确实适合 16 位。

然后我们接下来有什么?3e8,这是十进制 1000 的十六进制。

所以,我们已经证明这是一个标记指针——至少在我测试过的系统上(OS X 10.7.5 64 位)。

于 2013-07-12T13:15:53.890 回答
4

NSNumber是免费的桥接到CFNumber,这是开源的。从http://www.opensource.apple.com/source/CF/CF-476.19/CFNumber.c 你可以看到NSNumber 缓存了(-1)和 12 之间的整数值的创建对象,以便对象返回

[[NSNumber alloc] initWithInt:10]

永远不会被释放,并且多个调用返回相同的实例。

为了

[[NSNumber alloc] initWithInt:1000]

您可能会看到不同的行为。

于 2013-07-12T13:17:14.577 回答