object_id赋值如何工作?
我正在玩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之后,给定的string的object_id是绝不相同的。
这给我提出了几个问题:
- 有没有一个已知的scheme来确定某个
object_id
? 其他人基本上是随机的 - 真,假,零的ID不是连续的。 有没有办法来问什么对象是由给定的ID代表? (我很好奇其他的一位数字和id是绑在一起的)
- 你可以(不是你应该)写混淆的Ruby,在那里你使用已知的对象ID来引用对象而不命名它们,比如“ID为201的对象+ ID为19的对象”表示“100 + 9”?
更新
使用安德鲁·格林的build议,我试图发现其他“低ID”的对象,但发现:
- 在这个序列中似乎没有更多的偶数对象 – id 6,8,10等没有指向任何东西。
- 正如我之前的实验所暗示的,所有的奇数ID都属于数字。 具体而言,id 1指向数字0,3指向1,5指向2,依此类推。
在MRI中,对象的object_id
与表示C级别上的对象的VALUE
相同。 对于大多数types的对象,这个VALUE
是一个指向存储实际对象数据的内存位置的指针。 很显然,在多次运行中,这将是不同的,因为它只取决于系统决定分配内存的位置,而不取决于对象本身的任何属性。
然而,由于性能的原因, true
, false
, nil
和Fixnum
是专门处理。 对于这些对象,实际上并不存在与内存中的对象数据结构。 所有对象的数据都是在VALUE
编码的。 正如你已经知道false
, true
, nil
和Fixnum
i
分别是Fixnum
和i*2+1
。
这样做的原因是,在任何运行MRI的系统上,0,2,4和i*2+1
永远都不是堆中对象的有效地址,因此不会与指向对象数据的指针重叠。
分配整数(value * 2) + 1
和非整数(x * 2)
类似于大酒店的希尔伯特悖论 ,它描述了如何将无限多的客人分配给无限的酒店。
关于通过ID查找对象,有ObjectSpace._id2ref(object_id)
。 除非你的实现没有ObjectSpace。