我正在玩Ruby的.object_id
并注意到,在irb的几个连续会话中,我得到了相同的结果:
false.object_id // 0
true.object_id // 2
nil.object_id // 4
100.object_id // 201
实际上,每个整数的object_id似乎都是((value * 2)+ 1)。
另一方面,退出并重新运行irb后,给定字符串的object_id永远不会相同。
这给我提出了几个问题:
object_id
的已知方案?其他人基本上是随意的吗?使用Andrew Grimm的建议,我尝试发现其他“低id”对象,但发现:
答案 0 :(得分:62)
在MRI中,对象的object_id
与表示C级别对象的VALUE
相同。对于大多数类型的对象,此VALUE
是指向存储器中存储实际对象数据的位置的指针。显然,这在多次运行期间会有所不同,因为它只取决于系统决定分配内存的位置,而不取决于对象本身的任何属性。
但出于性能原因true
,false
,nil
和Fixnum
是专门处理的。对于这些对象,实际上并没有在内存中包含对象数据的结构。所有对象的数据都在VALUE
本身进行编码。正如您已经确定false
,true
,nil
和任何Fixnum
i
的值,0
,2
,4
和i*2+1
。
这样做的原因是,在运行MRI的任何系统上,0
,2
,4
和i*2+1
永远不会是有效的地址。堆,所以与指向对象数据的指针没有重叠。
答案 1 :(得分:31)
分配整数(value * 2) + 1
和非整数(x * 2)
类似于Hilbert's paradox of the Grand Hotel,它描述了如何将无限多的客人分配给无限酒店。
关于按ID查找对象,有ObjectSpace._id2ref(object_id)
。除非您的实现没有ObjectSpace。