<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Ruby_Infant (杂毛小道)</title>
    <link>https://ruby-china.org/Ruby_Infant</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>Ruby 学习笔记</title>
      <description>&lt;p&gt;最近开始学习 Ruby，现在整理一下自己学习的笔记，针对的 Ruby 是 MRI 版。其中难免有错误之处，还望大家批评指正。下面是链接：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ruby-china.org/notes/4019" title=""&gt; 对象模型&lt;/a&gt;&lt;br&gt;
&lt;a href="https://ruby-china.org/notes/4020" title=""&gt; 类模型&lt;/a&gt;&lt;br&gt;
&lt;a href="https://ruby-china.org/notes/4049" title=""&gt;方法的定义&lt;/a&gt;&lt;/p&gt;</description>
      <author>Ruby_Infant</author>
      <pubDate>Mon, 17 Apr 2017 15:49:43 +0800</pubDate>
      <link>https://ruby-china.org/topics/32799</link>
      <guid>https://ruby-china.org/topics/32799</guid>
    </item>
    <item>
      <title>Ruby 学习笔记--对象模型</title>
      <description>&lt;p&gt;最近开始学习 Ruby，现在整理一下自己学习的笔记，针对的 Ruby 是 MRI 版。其中难免有错误之处，还望大家批评指正。&lt;/p&gt;
&lt;h4 id="自定义类对象模型"&gt;自定义类对象模型&lt;/h4&gt;
&lt;p&gt;在源代码中可以看到 Ruby 使用 RObject 结构体来存储自定义类对象以及 Ruby 内部创建的少数自定义类，代码如下：&lt;/p&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;RBasic&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;klass&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cp"&gt;#define ROBJECT_EMBED_LEN_MAX 3
&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;RObject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;RBasic&lt;/span&gt; &lt;span class="n"&gt;basic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;union&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;numiv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ivptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;st_table&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;iv_index_tbl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;heap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ROBJECT_EMBED_LEN_MAX&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其中各部分的含义如下：&lt;br&gt;
numiv:  实例变量的数目；&lt;br&gt;
*ivptr:   实例变量值数组的指针，这里只保存值；&lt;br&gt;
*iv_index_tbl:  指向一个散列表，该散列表是实例变量名及其在 ivptr 数组中位置的映射，这只是一个缓存，真实的散列是在对象对应的类的 RClass 结构体中的。&lt;br&gt;
ary:  从代码中可以看出，ary 和上述三个变量使用同一块内存空间，它被用来保存实例变量。如果属性个数小于 ROBJECT_EMBED_LEN_MAX 属性值将直接存储在 ary 数组内，如果变量的大小合适，就会被全部保存，这样就不需要为了保存实例变量的值的数组而调用 malloc 来分配额外的内存；否则属性值和索引都存储在 heap 结构体中。  &lt;/p&gt;

&lt;p&gt;用一个图来表示如下图所示 (假设 ROBJECT_EMBED_LEN_MAX=1)：&lt;br&gt;
&lt;img src="https://l.ruby-china.com/photo/2017/01785dc2-c1aa-472c-8d0c-d02a0a973be3.png!large" title="" alt=""&gt;&lt;br&gt;
当我们使用 obj = ClassName.new 来创建一个对象的时候，obj 中会存储属于自己的实例变量的信息，同一个类的不同对象可能拥有不同个数的实例变量。同时 obj 的 klass 会指向自己的类。也就是说：  &lt;/p&gt;
&lt;h5 id="每个Ruby对象都是类指针和实例变量数组的组合。"&gt;每个 Ruby 对象都是类指针和实例变量数组的组合。&lt;/h5&gt;&lt;h4 id="基本类型对象模型"&gt;基本类型对象模型&lt;/h4&gt;
&lt;p&gt;在 Ruby 中一切皆对象，基本的数据类型也是一样的。Ruby 使用了别的结构体来保存每个基本数据类型的值。如使用 RString 结构体保存字符串的值，使用 RArray 结构体保存数组等。但是，这些不同的结构体中都包含同样的 RBasic 结构体。如下图所示的是 RString 的简化版：&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2017/c1203ac1-ec7c-462c-b77a-3c75548450b4.png!large" title="" alt=""&gt;&lt;br&gt;
在 RString、RArray、RStruct 和 RBignum 结构体中同样使用了 ary 数组来优化内存。&lt;br&gt;
此外，为了优化性能，Ruby 中保存小值整数、符号和其他一些简单立即值时没有使用任何结构体，只是将值放在 VALUE 中。在源码中，VALUE 的定义如下：  &lt;/p&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;VALUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;VALUE 可以看作是 long 类型的一个别名。在这里，Ruby 将其分为两部分：值和标志位。&lt;br&gt;
&lt;img src="https://l.ruby-china.com/photo/2017/8a1a6659-8b9a-4adb-a4d5-c05f479e4b57.png!large" title="" alt=""&gt;  &lt;/p&gt;

&lt;p&gt;在这里 VALUE 不在是指针，它们就是值本身。前几个比特存储值，后边的就是标志位。全部小值整数都有 FIXNUM_FLAG 位标记。&lt;br&gt;
&lt;img src="https://l.ruby-china.com/photo/2017/83e9756a-8162-4fd2-b679-2bac2d31a5fd.png!large" title="" alt=""&gt;&lt;br&gt;
一旦 FIXNUM_FLAG 被设置，Ruby 就知道这个 VALUE 是一个小值整数，而不是指向结构体的指针。&lt;br&gt;
在 Ruby 中，使用这种方式实现的类型还有 Symbol，true，false，nil 和 undef。从中可以看出为什么字符占用的资源比符号要多。  &lt;/p&gt;

&lt;p&gt;参考：&lt;br&gt;
《Ruby 原理剖析》&lt;br&gt;
&lt;a href="https://segmentfault.com/a/1190000008213542" rel="nofollow" target="_blank" title=""&gt;xingpingz  Ruby 2.X 源代码学习：对象模型 &lt;/a&gt;&lt;/p&gt;</description>
      <author>Ruby_Infant</author>
      <pubDate>Mon, 17 Apr 2017 15:31:39 +0800</pubDate>
      <link>https://ruby-china.org/topics/32798</link>
      <guid>https://ruby-china.org/topics/32798</guid>
    </item>
  </channel>
</rss>
