首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >一些“`Fixnum`”性质

一些“`Fixnum`”性质
EN

Stack Overflow用户
提问于 2013-03-06 14:40:20
回答 2查看 747关注 0票数 2

我在Fixnum中找到了文档的以下特性。

Fixnum对象具有即时值。这意味着当它们作为参数分配或传递时,将传递实际的对象,而不是对该对象的引用。

在IRB中可以显示相同的内容吗?希望只有它才能被我正确理解?

赋值不别名Fixnum对象。

那究竟是什么呢?

对于任何给定的整数值,实际上只有一个Fixnum对象实例,因此,例如,您不能向Fixnum添加单例方法。

无法理解不使用singleton对象实例添加Fixnum方法的原因。

我对第二点作了一些尝试,具体如下:

代码语言:javascript
复制
a = 1                      # => 1
a.class                    # => Fixnum
b = a                      # => 1
b.class                    # => Fixnum
a == b                     # => true
a.equal? b                 # => true
a.object_id == b.object_id # => true

但我还是很困惑。有谁能帮我了解一下这些功能的核心吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-03-07 01:15:30

在Ruby中,大多数对象需要内存来存储它们的类和实例变量。一旦分配了这个内存,Ruby就会根据这个内存位置来表示每个对象。当对象被分配给一个变量或传递给一个函数时,传递的是这个内存的位置,而不是这个内存中的数据。Singleton方法利用了这一点。当您定义单例方法时,Ruby悄悄地用一个新的单例类替换对象类。因为每个对象都存储其类,Ruby可以轻松地用一个实现单例方法(并从原始类继承)的新类替换对象的类。

对于直接值的对象,这不再是正确的:truefalsenil、所有符号以及足够小到适合于Fixnum的整数。Ruby不为这些对象的实例分配内存,也不将对象内部表示为内存中的位置。相反,它根据对象的内部表示来推断对象的实例。这意味着有两个方面:

  1. 每个对象的类不再存储在特定位置的内存中,而是由直接对象的类型隐式确定。这就是为什么Fixnum不能有单例方法的原因。
  2. 具有相同状态的直接对象(例如,整数2378的两个Fixnum)实际上是相同的实例。这是因为实例是由此状态决定的。

要更好地理解这一点,请考虑在Fixnum上执行以下操作:

代码语言:javascript
复制
>> x = 3 + 7
=> 10
>> x.object_id == 10.object_id
=> true
>> x.object_id == (15-5).object_id
=> true

现在,考虑使用字符串:

代码语言:javascript
复制
>> x = "a" + "b"
=> "ab"
>> x.object_id == "ab".object_id
=> false
>> x.object_id == "Xab"[1...3].object_id
=> false
>> x == "ab"
=> true
>> x == "Xab"[1...3]
=> true

Fixnum的对象ids相等的原因是它们是具有相同内部表示的直接对象。另一方面,字符串存在于已分配的内存中。每个字符串的对象id是其对象状态在内存中的位置。

一些低级信息

要理解这一点,您必须了解Ruby (至少1.8和1.9)如何在内部处理Fixnum。在Ruby中,所有对象都用VALUE类型的变量在C代码中表示。Ruby对VALUE提出了以下要求

  1. 类型值是足够大小的最小整数,足以容纳指针。这意味着,在C中,sizeof(VALUE) == sizeof(void*)
  2. 任何非即时对象都必须在4字节的边界上对齐.这意味着,由Ruby分配的任何对象都将具有地址4*i,用于某些整数i。这也意味着所有指针的两个最不重要位的值都为零。

第一个需求允许Ruby将指向对象的指针和直接值存储在VALUE类型的变量中。第二个需求允许Ruby基于两个最不重要的位来检测Fixnum和符号对象。

为了使这更具体,请考虑Ruby对象z的内部二进制表示,我们将在32位体系结构中将其称为Rz

代码语言:javascript
复制
MSB                                   LSB
  3           2            1            
 1098 7654 3210 9876 5432 1098 7654 32 10
 XXXX XXXX XXXX XXXX XXXX XXXX XXXX AB CD

然后,Ruby将Rz ( z的表示形式)解释为:

  1. 如果是D==1,那么z就是Fixnum。此Fixnum的整数值存储在表示的上31位中,并通过执行算术右移来恢复存储在这些位中的有符号整数。
  2. 测试了三种特殊的表示(都使用了D==0)
代码语言:javascript
复制
- if `Rz==0`, then `z` is `false`
- if `Rz==2`, then `z` is `true`
- if `Rz==4`, then `z` is `nil`

  1. 如果是ABCD == 1110,那么z就是一个符号。通过右移八个最不重要的位(即C中的z>>8 ),符号被转换成唯一的ID。在32位架构上,这允许2^24个不同的ID(超过1,000万).在64位架构上,这允许2^48个不同的ID.
  2. 否则,Rz表示Ruby对象实例在内存中的地址,z的类型由该位置的类信息决定。
票数 11
EN

Stack Overflow用户

发布于 2013-03-06 14:52:20

好吧..。

  1. 这是MRI的内部实现细节。您可以看到,在Ruby中(在C端),所有的Ruby对象都是一个VALUE。在大多数情况下,VALUE是指向存在于堆栈上的对象的指针。但是即时值(Fixnum、true、false、nil等)存在于VALUE中,指向对象的指针通常在其中存在。
  2. 它使变量成为完全相同的对象。现在,我不知道这在内部是如何工作的,因为它将它分配给VALUE本身,但它确实这样做了。
  3. 因为每次在我的程序中使用数字1时,我都使用相同的对象。因此,如果我在1上定义了一个单例方法,那么我的程序中的每一个地方,所需的程序等等,都会有这个单例方法。单例方法通常用于局部猴子识别。所以,为了防止这种情况,Ruby只是不让你。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15250212

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档