16

我在某个时候遇到了这个ruby​​ object_id 分配问题,然后阅读了这篇很棒的文章,它讨论了 VALUE 并解释了为什么 object_id 的 true、nil 和 false 是这样的。当我发现关于 true 和 nil 的 object_id 的明显变化时,我一直在玩弄 ruby​​2.0 object_id。

forbidden:~$ ruby -v
ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-linux]
forbidden:~$
forbidden:~$ irb
irb(main):001:0> true.object_id
=> 20
irb(main):002:0> false.object_id
=> 0
irb(main):003:0> nil.object_id
=> 8
irb(main):004:0> exit
forbidden:~$
forbidden:~$ rvm use 1.9.3
Using /home/forbidden/.rvm/gems/ruby-1.9.3-p392
forbidden:~$ ruby -v
ruby 1.9.3p392 (2013-02-22 revision 39386) [x86_64-linux]
forbidden:~$
forbidden:~$ irb
irb(main):001:0> true.object_id
=> 2
irb(main):002:0> false.object_id
=> 0
irb(main):003:0> nil.object_id
=> 4

tl;dr: true 和 nil 的值在 1.9.3 和 1.8.7 中分别为 2、4,但在 ruby​​2.0.0 中已更改为 20、8 - 即使 false 的 id 保持不变,即 0 和Fixnum 的 ids 保持相同的旧 2n+1 模式。

此外,Fixnum 和 Bignum 的实现方式在 2.0.0 中仍然是相同的,因为上面提到的文章中给出的示例也与以前相同的方式运行:

irb(main):001:0> 
irb(main):002:0* ((2**62)).class
=> Bignum
irb(main):003:0> ((2**62)-1).class
=> Fixnum
irb(main):004:0>

这个 object_id 变化背后的原因是什么?

为什么会做出这样的改变?这将如何帮助开发人员?

4

1 回答 1

19

查看定义这些值的 Ruby 源代码表明这与“flonums”有关(另请参阅引入它的提交)。搜索“flonum”时,Ruby 邮件列表中出现了一条讨论它的消息。

这是一种通过对某些浮点值使用立即值来加速 64 位机器上的浮点计算的技术,类似于对整数使用 Fixnums。Flonums 的模式是...xxxx xx10(即最后两位是10,而对于 fixnums 的最后一位是1)。其他立即数的object_ids 已更改以适应此更改。

object_id通过查看Ruby 1.9.3 和 2.0.0 中的浮点数,您可以看到这种变化。

在 1.9.3 中,具有相同值的不同浮点数是不同的对象:

1.9.3p385 :001 > s = 10.234
 => 10.234 
1.9.3p385 :002 > t = 10.234
 => 10.234 
1.9.3p385 :003 > s.object_id
 => 2160496240 
1.9.3p385 :004 > t.object_id
 => 2160508080 

在 2.0.0 中它们是相同的:

2.0.0p0 :001 > s = 10.234
 => 10.234 
2.0.0p0 :002 > t = 10.234
 => 10.234 
2.0.0p0 :003 > s.object_id
 => 82118635605473626 
2.0.0p0 :004 > t.object_id
 => 82118635605473626 
于 2013-03-20T14:47:09.900 回答