PHP5和PHP7引用對比(筆記)

php5在引入引用計數後,使用了refcount_gc來記錄次數,同時使用is_ref_gc來記錄是不是引用類型。php

例如php7

$a = 'hello';內存

//$a->zval1(type=IS_STRING,refcount_gc=1,is_ref_gc=0)字符串

這個時候$a指向一個結構體,主要看refcount_gc=1,這就是引用計數字段,由於hello這個字符串被賦值給了$a,因此這個時候hello的引用計數就是1string

$b = $a;引用

$b,$a->zval1(type=IS_STRING,refcount_gc=2,is_ref_gc=0)gc

這個時候又把$a賦值給了$b,因此這個時候$b和$a同時指向這個結構體,而且引用計數加1co

$c = &$b;字符

//$a->zval1(type=IS_STRING,refcount_gc=1,is_ref_gc=0)數字

//$c,$b->zval2(type=IS_STRING,refcount_gc=2,is_ref_gc=1)

這個時候由於把$b賦值給了$c,可是是傳址的方式,因此在這個時候就要分離了,$a還指向原來的結構體,$c和$b同時指向一個新的結構體,這個時候zval的is_ref_gc值會改變,使得此時的zval必須進行分離,可是實際上他們的值尚未變化,這使得須要在堆中維護兩個值爲"hello"的zval。

下面咱們來看看php7中的實現

php7引入了新的類型IS_REFERENCE來處理這個問題,首先看看zend_reference的結構體:

struct _zend_reference{

zend_refcounted_h gc;

zval val;

};

$a = 'hello';

//$a->zend_string(refcount=1,val)

$b = $a;

//$b,$a->zend_string(refcount=2,val)

$c = &$b;

//$a->zend_string(refcount=2,val)

//$c,$b->zval(type=IS_REFERENCE,refcount=2)->zend_string(refcount=2,val)

從上面能夠看出來,當使用&操做時,會建立一種新的中間結構體zend_referenct,這個結構體會指向真正的zend_string結構體,因此zend_string結構體的引用計數不變,同時zend_reference結構體的引用計數變爲2,由於$c和$b此時的類型都會變爲zend_reference,這樣的好處是原始的zend_string在內存中始終只有一份(避免了因爲字符串的重複申請致使的內存浪費),更加易於維護。

相關文章
相關標籤/搜索