object_id赋值如何工作?

时间:2010-08-07 11:41:25

标签: ruby internals

我正在玩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永远不会相同。

这给我提出了几个问题:

  1. 是否有确定某些object_id的已知方案?其他人基本上是随意的吗?
  2. true,false和nil的id不是顺序的。有没有办法询问给定id表示的对象是什么? (我很好奇其他一位数和ids的关系。)
  3. 你可以(不是你应该)编写模糊的Ruby,你使用已知的对象id引用对象而不命名它们,比如“id 201的对象+ id为19的对象”意味着“100 + 9”?
  4. 更新

    使用Andrew Grimm的建议,我尝试发现其他“低id”对象,但发现:

    • 此序列中似乎没有任何偶数对象 - ids 6,8,10等不指向任何内容。
    • 正如我之前的实验所暗示的那样,所有奇数编号的id都属于数字。具体而言,id 1指向数字0,3指向1,5指向2,依此类推。

2 个答案:

答案 0 :(得分:62)

在MRI中,对象的object_id与表示C级别对象的VALUE相同。对于大多数类型的对象,此VALUE是指向存储器中存储实际对象数据的位置的指针。显然,这在多次运行期间会有所不同,因为它只取决于系统决定分配内存的位置,而不取决于对象本身的任何属性。

但出于性能原因truefalsenilFixnum是专门处理的。对于这些对象,实际上并没有在内存中包含对象数据的结构。所有对象的数据都在VALUE本身进行编码。正如您已经确定falsetruenil和任何Fixnum i的值,024i*2+1

这样做的原因是,在运行MRI的任何系统上,024i*2+1永远不会是有效的地址。堆,所以与指向对象数据的指针没有重叠。

答案 1 :(得分:31)

分配整数(value * 2) + 1和非整数(x * 2)类似于Hilbert's paradox of the Grand Hotel,它描述了如何将无限多的客人分配给无限酒店。

关于按ID查找对象,有ObjectSpace._id2ref(object_id)。除非您的实现没有ObjectSpace。