深入解析PHP的引用計數機制_php技巧

來源:互聯網
上載者:User

PHP的變數聲明並賦值後,變數名存在符號表中,而值和類資訊存在zval中,zval中包含四個變數,is_ref,refcount,value,type,zval源碼如下

複製代碼 代碼如下:

struct _zval_struct { 
    /* Variable information */ 
    zvalue_value value;     /* value */ 
    zend_uint refcount__gc; 
    zend_uchar type;    /* active type */ 
    zend_uchar is_ref__gc; 
};

refcount表示value地址與其相同的zval共有多少個,refcount=0時,zval被銷毀
is_ref表示一個zval是否被引用,有“0”和“1”兩種狀態

此處分析一下什麼時候zval會被複製或者開闢新的記憶體空間呢
1.當is_ref=0,且refcount>1時,如果改變某個指向該zval的變數的值,會產生新zval,原zval的refcount--,例如:$a=1;$b=$a;$b=2;,zval將被複製,也就是說原先ab指向同一個zval,後來b會使用新開闢的zval

2.當is_ref=0,且refcount>1時,如果將zval賦值給某個引用變數,那麼用來賦值和變數和被賦值的變數會使用同一個原zval,而其他指向原zval的變數將會指向一個新複製的zval,且refcount會被重新計算,例如:$a=1;$b=$a;$c=$a;$d=&$a;,此時ad使用原zval,bc使用新複製出來的zval

3.當is_ref=1,且refcount>1時,如果將zval複製給某個非引用變數,該非引用變數會使用一個新複製的zval,元zval的refcount不變,例如:$a=1;$b=&$a;$c=$a,那麼ab使用原zval,而c使用新複製的zval
type表示該zval的實值型別,宏定義如下

複製代碼 代碼如下:

#define IS_NULL     0 
#define IS_LONG     1 
#define IS_DOUBLE   2 
#define IS_BOOL     3 
#define IS_ARRAY    4 
#define IS_OBJECT   5 
#define IS_STRING   6 
#define IS_RESOURCE 7 
#define IS_CONSTANT 8 
#define IS_CONSTANT_ARRAY   9

value表示該zval的值,他也是個共同體,代碼如下
複製代碼 代碼如下:

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;

現在你知道php是如何類型變換的了,因為他的值存的其實是個可以代表任何類型的結構體,而具體的取值則根據type來決定是用共同體裡的哪個變數來存值的

見下面的例子1
複製代碼 代碼如下:

.-----------
$a = 1;
$b = $a;
$c = $a;
.-----------
$d = &$a;
.-----------
$a = 2;
.-----------
$b = null;

查看refcount,is_ref,zval的變化
執行完第一部分後來看看輸出
1-----------------------------
a:(refcount=3, is_ref=0),int 1
b:(refcount=3, is_ref=0),int 1
c:(refcount=3, is_ref=0),int 1
可以看出來a,b,c使用同一個zval
再看執行完第二部分的
2----------------------------
a:(refcount=2, is_ref=1),int 1
b:(refcount=2, is_ref=0),int 1
c:(refcount=2, is_ref=0),int 1
d:(refcount=2, is_ref=1),int 1
注意此時a,d在一起了,他們使用同一個zval,而bc使用一個新產生的zval,同時重新計算兩個zval的refcount和is_ref
3----------------------------
a:(refcount=2, is_ref=1),int 2
b:(refcount=2, is_ref=0),int 1
c:(refcount=2, is_ref=0),int 1
d:(refcount=2, is_ref=1),int 2
可以知道ad這兩個is_ref=1的好基友的值是同時改變的
4----------------------------
a:(refcount=2, is_ref=1),int 2
b:(refcount=1, is_ref=0),null
c:(refcount=1, is_ref=0),int 1
d:(refcount=2, is_ref=1),int 2
bc由於他們的zval的is_ref=0,所以他們不是好基友,他們的值不會同時改變,於是bc的zval再次分裂,b = null c = 1

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.