一些`Fixnum`属性

Aru*_*hit 2 ruby

Fixnumdoc中找到了以下功能.

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

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

赋值不会为Fixnum对象添加别名.

它究竟是什么呢?

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

无法理解不在对象实例中添加singleton方法的原因Fixnum.

我尝试了第二点,如下所示:

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
Run Code Online (Sandbox Code Playgroud)

但我仍然感到困惑.任何人都可以帮我在这里了解这些功能的核心吗?

sfs*_*man 10

在Ruby中,大多数对象都需要内存来存储它们的类和实例变量.分配此内存后,Ruby通过此内存位置表示每个对象.将对象分配给变量或传递给函数时,它是传递此内存的位置,而不是此内存中的数据.单身方法利用了这一点.定义单例方法时,Ruby会默默地用新的单例类替换对象类.因为每个对象都存储它的类,所以Ruby可以很容易地用一个实现单例方法的新类替换一个对象的类(并继承自原始类).

这绝不是对于那些直接值的对象不再是这样:true,false,nil足够小,以适应一个Fixnum内,所有符号和整数.Ruby不为这些对象的实例分配内存,它不在内部将对象表示为内存中的位置.相反,它基于其内部表示推断对象的实例.这意味着什么是双重的:

  1. 每个对象的类不再存储在特定位置的存储器中,而是由直接对象的类型隐式确定.这就是Fixnums不能使用单例方法的原因.

  2. 具有相同状态的直接对象(例如,两个整数2378的Fixnum)实际上是相同的实例.这是因为实例是由这种状态决定的.

为了更好地理解这一点,请考虑Fixnum上的以下操作:

>> x = 3 + 7
=> 10
>> x.object_id == 10.object_id
=> true
>> x.object_id == (15-5).object_id
=> true
Run Code Online (Sandbox Code Playgroud)

现在,考虑使用字符串:

>> 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
Run Code Online (Sandbox Code Playgroud)

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

一些低级别的信息

要理解这一点,您必须了解Ruby(至少1.8和1.9)如何在内部处理Fixnums.在Ruby中,所有对象都由C代码中的变量表示VALUE.Ruby对以下要求强加了以下要求VALUE:

  1. VALUE类型是保存指针的足够大小的最小整数.这意味着,在C中sizeof(VALUE) == sizeof(void*).

  2. 任何非直接对象必须在4字节边界上对齐.这意味着Ruby分配的任何对象都将具有4*i某个整数的地址i.这也意味着所有指针在其两个最低有效位中都具有零值.

第一个要求允许Ruby将指向对象的指针和立即值存储在类型的变量中VALUE.第二个要求允许Ruby根据两个最低有效位检测Fixnum和Symbol对象.

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

MSB                                   LSB
  3           2            1            
 1098 7654 3210 9876 5432 1098 7654 32 10
 XXXX XXXX XXXX XXXX XXXX XXXX XXXX AB CD
Run Code Online (Sandbox Code Playgroud)

Ruby然后解释Rz,表示z如下:

  1. 如果D==1,则z是Fixnum.该Fixnum的整数值存储在表示的高31位中,并通过执行算术右移以恢复存储在这些位中的有符号整数来恢复.

  2. 测试了三个特殊表示(全部用D==0)

    • 如果Rz==0,然后zfalse
    • 如果Rz==2,然后ztrue
    • 如果Rz==4,然后znil
  3. 如果ABCD == 1110,则'z'是符号.通过右移八个最低有效位(即,z>>8在C中)将符号转换为唯一ID .在32位架构上,这允许2 ^ 24个不同的ID(超过1000万).在64位体系结构上,这允许2 ^ 48个不同的ID.

  4. 否则,Rz表示内存中的Ruby对象实例的地址,其类型z由该位置的类信息确定.