在Ruby中,为什么inspect()打印出某种与object_id()给出的不同的对象id?

发布于 2024-08-31 21:44:21 字数 387 浏览 6 评论 0原文

p函数用于打印对象时,它可能会给出一个ID,它与object_id()给出的不同。数字不同的原因是什么?

更新: 0x4684abc36971870 不同,即 0x234255E

>> a = Point.new
=> #<Point:0x4684abc>

>> a.object_id
=> 36971870

>> a.__id__
=> 36971870

>> "%X" % a.object_id
=> "234255E"

When the p function is used to print out an object, it may give an ID, and it is different from what object_id() gives. What is the reason for the different numbers?

Update: 0x4684abc is different from 36971870, which is 0x234255E

>> a = Point.new
=> #<Point:0x4684abc>

>> a.object_id
=> 36971870

>> a.__id__
=> 36971870

>> "%X" % a.object_id
=> "234255E"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烟─花易冷 2024-09-07 21:44:21

inspect 的默认实现调用了 to_s 的默认实现,它只是直接显示对象的十六进制值,如 Object#to_s 中所示> docs(点击方法描述即可显示源代码)。

同时,object_id 实现的 C 源代码中的注释表明,根据对象的类型,Ruby 值和对象 id 有不同的“命名空间”(例如,最低位似乎为零对于除 Fixnums 之外的所有对象)。您可以在 Object#object_id docs 中看到这一点(点击即可显示来源)。

从那里我们可以看到,在“object id space”(由 object_id 返回)中,对象的 id 从右侧第二位开始(第一位为零),但在“value space”(由 inspect 使用),它们从右侧的第三位开始(前两位为零)。因此,要将值从“对象 id 空间”转换为“值空间”,我们可以将 object_id 向左移动一位,并得到与 显示的相同结果检查

> '%x' % (36971870 << 1)
=> "4684abc"

> a = Foo.new
=> #<Foo:0x5cfe4>
> '%x' % (a.object_id << 1)
=> "5cfe4"

注意:有关object_id的详细信息在当时(2010年)是正确的,但在新的Ruby版本解耦object_id之后就不再正确了 来自内存地址。现在答案更接近“因为 object_id 是按需生成的”。见评论。

The default implementation of inspect calls the default implementation of to_s, which just shows the hexadecimal value of the object directly, as seen in the Object#to_s docs (click on the method description to reveal the source).

Meanwhile the comments in the C source underlying the implementation of object_id shows that there are different “namespaces” for Ruby values and object ids, depending on the type of the object (e.g. the lowest bit seems to be zero for all but Fixnums). You can see that in Object#object_id docs (click to reveal the source).

From there we can see that in the “object id space” (returned by object_id) the ids of objects start from the second bit on the right (with the first bit being zero), but in “value space” (used by inspect) they start from the third bit on the right (with the first two bits zero). So, to convert the values from the “object id space” to the “value space”, we can shift the object_id to the left by one bit and get the same result that is shown by inspect:

> '%x' % (36971870 << 1)
=> "4684abc"

> a = Foo.new
=> #<Foo:0x5cfe4>
> '%x' % (a.object_id << 1)
=> "5cfe4"

Note: The details about object_id were correct at the time (2010), but aren't anymore after newer Ruby versions have decoupled object_id from memory addresses. Now the answer is more along the lines "because object_id is generated on demand". See comments.

晨光如昨 2024-09-07 21:44:21
0x234255E

=>36971870

没有什么不同,都是内存地址的十六进制表示:-)

0x234255E

=>36971870

It's not different, it's the hexadecimal representation of the memory address:-)

人生戏 2024-09-07 21:44:21

Ruby 2.7 版本将对象的 object_id 与内存地址本身解耦,因此您无法将 object_id 转换为内存地址,反之亦然。事实上,对象的实际地址可以更改,而其 object_id 保持不变。

也就是说,根据您的 Ruby 版本,ObjectSpace 模块可能能够返回对象的内存地址。注意:该库经常更改,因此很可能您应该只在控制台中使用它。

# Using Ruby version 2.7.8 -- this code may not work in later versions!

require "objspace"
require "json"

object = Object.new
#=> #<Object:0x00007ff174981a08>

object_internals_json = ObjectSpace.dump(object)
#=> "{\"address\":\"0x7ff174981a08\", \"type\":\"OBJECT\", \"class\":\"0x7ff18d991250\", \"ivars\":0, \"memsize\":40, \"flags\":{\"wb_protected\":true}}\n"

JSON.parse(object_internals_json)["address"]
#=> "0x7ff174981a08"

Ruby version 2.7 decoupled the object's object_id from the memory address itself, so you can't transform an object_id into a memory address or vice versa. In fact, the object's actual address can change while its object_id remains the same.

That said, depending on your Ruby version, the ObjectSpace module might be able to return an object's memory address. Note: this library changes frequently, so most likely you should only use it in the console.

# Using Ruby version 2.7.8 -- this code may not work in later versions!

require "objspace"
require "json"

object = Object.new
#=> #<Object:0x00007ff174981a08>

object_internals_json = ObjectSpace.dump(object)
#=> "{\"address\":\"0x7ff174981a08\", \"type\":\"OBJECT\", \"class\":\"0x7ff18d991250\", \"ivars\":0, \"memsize\":40, \"flags\":{\"wb_protected\":true}}\n"

JSON.parse(object_internals_json)["address"]
#=> "0x7ff174981a08"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文