<delect id="sj01t"></delect>
  1. <em id="sj01t"><label id="sj01t"></label></em>
  2. <div id="sj01t"></div>
    1. <em id="sj01t"></em>

            <div id="sj01t"></div>
            php語言

            深入PHP變量存儲的詳解

            時間:2025-02-14 15:30:37 php語言 我要投稿
            • 相關推薦

            深入PHP變量存儲的詳解

              文章是對PHP變量的存儲進行了詳細的分析介紹,需要的朋友參考下,就跟隨百分網小編一起去了解下吧,想了解更多相關信息請持續關注我們應屆畢業生考試網!

              1.1.1 zval結構

              Zend使用zval結構來存儲PHP變量的值,該結構如下所示:

              復制代碼 代碼如下:

              typedef union _zvalue_value {

              long lval;    /* long value */

              double dval;    /* double value */

              struct {

              char *val;

              int len;

              } str;

              HashTable *ht;    /* hash table value */

              zend_object_value obj;

              } zvalue_value;

              struct _zval_struct {

              /* Variable information */

              zvalue_value value;  /* value */

              zend_uint refcount;

              zend_uchar type;   /* active type */

              zend_uchar is_ref;

              };

              typedef struct _zval_struct zval;

              Zend根據type值來決定訪問value的哪個成員,可用值如下:

              IS_NULL

              N/A

              IS_LONG

              對應value.lval

              IS_DOUBLE

              對應value.dval

              IS_STRING

              對應value.str

              IS_ARRAY

              對應value.ht

              IS_OBJECT

              對應value.obj

              IS_BOOL

              對應value.lval.

              IS_RESOURCE

              對應value.lval

              根據這個表格可以發現兩個有意思的地方:首先是PHP的數組其實就是一個HashTable,這就解釋了為什么PHP能夠支持關聯數組了;其次,Resource就是一個long值,它里面存放的通常是個指針、一個內部數組的index或者其它什么只有創建者自己才知道的東西,可以將其視作一個handle。

              1.1.2 引用計數

              引用計數在垃圾收集、內存池以及字符串等地方應用廣泛,Zend就實現了典型的引用計數。多個PHP變量可以通過引用計數機制來共享同一份zval,zval中剩余的兩個成員is_ref和refcount就用來支持這種共享。

              很明顯,refcount用于計數,當增減引用時,這個值也相應的遞增和遞減,一旦減到零,Zend就會回收該zval。

              那么is_ref呢?

              1.1.3 zval狀態

              在PHP中,變量有兩種——引用和非引用的,它們在Zend中都是采用引用計數的方式存儲的。對于非引用型變量,要求變量間互不相干,修改一個變量時,不能影響到其他變量,采用Copy-On-Write機制即可解決這種沖突——當試圖寫入一個變量時,Zend若發現該變量指向的zval被多個變量共享,則為其復制一份refcount為1的zval,并遞減原zval的refcount,這個過程稱為“zval分離”。然而,對于引用型變量,其要求和非引用型相反,引用賦值的變量間必須是捆綁的,修改一個變量就修改了所有捆綁變量。

              可見,有必要指出當前zval的狀態,以分別應對這兩種情況,is_ref就是這個目的,它指出了當前所有指向該zval的變量是否是采用引用賦值的——要么全是引用,要么全不是。此時再修改一個變量,只有當發現其zval的is_ref為0,即非引用時,Zend才會執行Copy-On-Write。

              1.1.4 zval狀態切換

              當在一個zval上進行的所有賦值操作都是引用或者都是非引用時,一個is_ref就足夠應付了。然而,世界總不會那么美好,PHP無法對用戶進行這種限制,當我們混合使用引用和非引用賦值時,就必須要進行特別處理了。

              情況I、看如下PHP代碼:

              復制代碼 代碼如下:

              <?php

              $a = 1;

              $b = $a;

              $c = $b;

              $d = &$c; // 在一堆非引用賦值中,插入一個引用

              ?>

              這段代碼首先進行了一次初始化,這將創建一個新的zval,is_ref=0, refcount=1,并將a指向這個zval;之后是兩次非引用賦值,正如前面所說,只要把b和c都指向a的zval即可;最后一行是個引用賦值,需要is_ref為1,但是Zend發現c指向的zval并不是引用型的,于是為c創建單獨的zval,并同時將d指向該zval。

              從本質上來說,這也可以看作是一種Copy-On-Write,不僅僅是value,is_ref也是受保護的對象。

              整個過程圖示如下:

              情況II,看如下PHP代碼:

              復制代碼 代碼如下:

              <?php

              $a = 1;

              $b = &$a;

              $c = &$b;

              $d = $c; // 在一堆引用賦值中,插入一個非引用

              ?>

              這段代碼的前三句將把a、b和c指向一個zval,其is_ref=1, refcount=3;第四句是個非引用賦值,通常情況下只需要增加引用計數即可,然而目標zval屬于引用變量,單純的增加引用計數顯然是錯誤的, Zend的解決辦法是為d單獨生成一份zval副本。

              全過程如下所示:

              1.1.5 參數傳遞

              PHP函數參數的傳遞和變量賦值是一樣的,非引用傳遞相當于非引用賦值,引用傳遞相當于引用賦值,并且也有可能會導致執行zval狀態切換。這在后面還將提到。

            【深入PHP變量存儲的詳解】相關文章:

            php變量作用域的深入解析07-18

            PHP的變量03-28

            PHP數據類型之數組變量詳解12-28

            什么是PHP的變量07-29

            PHP的變量介紹04-20

            PHP變量介紹02-28

            C語言變量存儲布局07-05

            php靜態成員變量06-22

            PHP的變量是什么06-10

            <delect id="sj01t"></delect>
            1. <em id="sj01t"><label id="sj01t"></label></em>
            2. <div id="sj01t"></div>
              1. <em id="sj01t"></em>

                      <div id="sj01t"></div>
                      黄色视频在线观看