深入解析PHP的引用計(jì)數(shù)機(jī)制
PHP的變量聲明并賦值后,變量名存在符號(hào)表中,而值和類信息存在zval中,zval中包含四個(gè)變量,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共有多少個(gè),refcount=0時(shí),zval被銷毀
is_ref表示一個(gè)zval是否被引用,有“0”和“1”兩種狀態(tài)
此處分析一下什么時(shí)候zval會(huì)被復(fù)制或者開(kāi)辟新的內(nèi)存空間呢
1.當(dāng)is_ref=0,且refcount>1時(shí),如果改變某個(gè)指向該zval的變量的值,會(huì)生成新zval,原zval的refcount--,例如:$a=1;$b=$a;$b=2;,zval將被復(fù)制,也就是說(shuō)原先ab指向同一個(gè)zval,后來(lái)b會(huì)使用新開(kāi)辟的zval
2.當(dāng)is_ref=0,且refcount>1時(shí),如果將zval賦值給某個(gè)引用變量,那么用來(lái)賦值和變量和被賦值的變量會(huì)使用同一個(gè)原zval,而其他指向原zval的變量將會(huì)指向一個(gè)新復(fù)制的zval,且refcount會(huì)被重新計(jì)算,例如:$a=1;$b=$a;$c=$a;$d=&$a;,此時(shí)ad使用原zval,bc使用新復(fù)制出來(lái)的zval
3.當(dāng)is_ref=1,且refcount>1時(shí),如果將zval復(fù)制給某個(gè)非引用變量,該非引用變量會(huì)使用一個(gè)新復(fù)制的zval,元zval的refcount不變,例如:$a=1;$b=&$a;$c=$a,那么ab使用原zval,而c使用新復(fù)制的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的值,他也是個(gè)共同體,代碼如下
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;
現(xiàn)在你知道php是如何類型變換的了,因?yàn)樗闹荡娴钠鋵?shí)是個(gè)可以代表任何類型的結(jié)構(gòu)體,而具體的取值則根據(jù)type來(lái)決定是用共同體里的哪個(gè)變量來(lái)存值的
見(jiàn)下面的例子1
.-----------
$a = 1;
$b = $a;
$c = $a;
.-----------
$d = &$a;
.-----------
$a = 2;
.-----------
$b = null;
查看refcount,is_ref,zval的變化
執(zhí)行完第一部分后來(lái)看看輸出
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
可以看出來(lái)a,b,c使用同一個(gè)zval
再看執(zhí)行完第二部分的
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
注意此時(shí)a,d在一起了,他們使用同一個(gè)zval,而bc使用一個(gè)新生成的zval,同時(shí)重新計(jì)算兩個(gè)zval的refcount和is_ref
相關(guān)文章
在PHP中檢查PHP文件是否有語(yǔ)法錯(cuò)誤的方法
在網(wǎng)上找了一下。剛開(kāi)始以為 token_get_all()函數(shù)能處理語(yǔ)法錯(cuò)誤的問(wèn)題,結(jié)果發(fā)現(xiàn),它只是做簡(jiǎn)單的詞法分析。沒(méi)有辦法。后來(lái)到論壇上去問(wèn)了一下2009-12-12
php對(duì)圖像的各種處理函數(shù)代碼小結(jié)
這篇文章主要介紹了php的圖片處理實(shí)現(xiàn)代碼,包括縮放、剪裁、縮放、翻轉(zhuǎn)、旋轉(zhuǎn)、透明、銳化等圖片操作,需要的朋友可以參考下2013-07-07
PHP頁(yè)面實(shí)現(xiàn)定時(shí)跳轉(zhuǎn)的方法
這篇文章主要介紹了PHP頁(yè)面實(shí)現(xiàn)定時(shí)跳轉(zhuǎn)的方法,實(shí)例演示使用header函數(shù)來(lái)實(shí)現(xiàn)跳轉(zhuǎn)的技巧,需要的朋友可以參考下2014-10-10
PHP 匿名函數(shù)與注意事項(xiàng)詳細(xì)介紹
這篇文章主要介紹了PHP 匿名函數(shù)與注意事項(xiàng)詳細(xì)介紹的相關(guān)資料,匿名函數(shù)是PHP5.3引進(jìn)來(lái)了,php5.3不但引進(jìn)了匿名函數(shù)還有更多更好多新的特性了,下面我們一起來(lái)了解一下PHP匿名函數(shù)與注意事項(xiàng)詳解,需要的朋友可以參考下2016-11-11
php+ajax實(shí)時(shí)輸入自動(dòng)搜索匹配的方法
這篇文章主要介紹了php+ajax實(shí)時(shí)輸入自動(dòng)搜索匹配的方法,實(shí)例分析了兩種實(shí)現(xiàn)方法,是非常實(shí)用的技巧,需要的朋友可以參考下2014-12-12

