中文字幕日韩一区二区_国产一区二区av_国产毛片av_久久久久国产一区_色婷婷电影_国产一区二区精品

深入PHP變量存儲的詳解

1.1.1 zval結(jié)構(gòu)
Zend使用zval結(jié)構(gòu)來存儲php變量的值,該結(jié)構(gòu)如下所示:
復(fù)制代碼 代碼如下:
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根據(jù)type值來決定訪問value的哪個(gè)成員,可用值如下:

IS_NULL

N/A

IS_LONG

對應(yīng)value.lval

IS_DOUBLE

對應(yīng)value.dval

IS_STRING

對應(yīng)value.str

IS_ARRAY

對應(yīng)value.ht

IS_OBJECT

對應(yīng)value.obj

IS_BOOL

對應(yīng)value.lval.

IS_RESOURCE

對應(yīng)value.lval

根據(jù)這個(gè)表格可以發(fā)現(xiàn)兩個(gè)有意思的地方:首先是php的數(shù)組其實(shí)就是一個(gè)HashTable,這就解釋了為什么php能夠支持關(guān)聯(lián)數(shù)組了;其次,Resource就是一個(gè)long值,它里面存放的通常是個(gè)指針、一個(gè)內(nèi)部數(shù)組的index或者其它什么只有創(chuàng)建者自己才知道的東西,可以將其視作一個(gè)handle。

1.1.2 引用計(jì)數(shù)
引用計(jì)數(shù)在垃圾收集、內(nèi)存池以及字符串等地方應(yīng)用廣泛,Zend就實(shí)現(xiàn)了典型的引用計(jì)數(shù)。多個(gè)php變量可以通過引用計(jì)數(shù)機(jī)制來共享同一份zval,zval中剩余的兩個(gè)成員is_ref和refcount就用來支持這種共享。
很明顯,refcount用于計(jì)數(shù),當(dāng)增減引用時(shí),這個(gè)值也相應(yīng)的遞增和遞減,一旦減到零,Zend就會回收該zval。
那么is_ref呢?

1.1.3 zval狀態(tài)
php中,變量有兩種――引用和非引用的,它們在Zend中都是采用引用計(jì)數(shù)的方式存儲的。對于非引用型變量,要求變量間互不相干,修改一個(gè)變量時(shí),不能影響到其他變量,采用Copy-On-Write機(jī)制即可解決這種沖突――當(dāng)試圖寫入一個(gè)變量時(shí),Zend若發(fā)現(xiàn)該變量指向的zval被多個(gè)變量共享,則為其復(fù)制一份refcount為1的zval,并遞減原zval的refcount,這個(gè)過程稱為“zval分離”。然而,對于引用型變量,其要求和非引用型相反,引用賦值的變量間必須是捆綁的,修改一個(gè)變量就修改了所有捆綁變量。
可見,有必要指出當(dāng)前zval的狀態(tài),以分別應(yīng)對這兩種情況,is_ref就是這個(gè)目的,它指出了當(dāng)前所有指向該zval的變量是否是采用引用賦值的――要么全是引用,要么全不是。此時(shí)再修改一個(gè)變量,只有當(dāng)發(fā)現(xiàn)其zval的is_ref為0,即非引用時(shí),Zend才會執(zhí)行Copy-On-Write。

1.1.4 zval狀態(tài)切換
當(dāng)在一個(gè)zval上進(jìn)行的所有賦值操作都是引用或者都是非引用時(shí),一個(gè)is_ref就足夠應(yīng)付了。然而,世界總不會那么美好,php無法對用戶進(jìn)行這種限制,當(dāng)我們混合使用引用和非引用賦值時(shí),就必須要進(jìn)行特別處理了。
情況I、看如下php代碼:
復(fù)制代碼 代碼如下:
<?php
$a = 1;
$b = $a;
$c = $b;
$d = &$c; // 在一堆非引用賦值中,插入一個(gè)引用
?>

這段代碼首先進(jìn)行了一次初始化,這將創(chuàng)建一個(gè)新的zval,is_ref=0, refcount=1,并將a指向這個(gè)zval;之后是兩次非引用賦值,正如前面所說,只要把b和c都指向a的zval即可;最后一行是個(gè)引用賦值,需要is_ref為1,但是Zend發(fā)現(xiàn)c指向的zval并不是引用型的,于是為c創(chuàng)建單獨(dú)的zval,并同時(shí)將d指向該zval。
從本質(zhì)上來說,這也可以看作是一種Copy-On-Write,不僅僅是value,is_ref也是受保護(hù)的對象。
整個(gè)過程圖示如下:

情況II,看如下php代碼:
復(fù)制代碼 代碼如下:
<?php
$a = 1;
$b = &$a;
$c = &$b;
$d = $c; // 在一堆引用賦值中,插入一個(gè)非引用
?>

這段代碼的前三句將把a(bǔ)、b和c指向一個(gè)zval,其is_ref=1, refcount=3;第四句是個(gè)非引用賦值,通常情況下只需要增加引用計(jì)數(shù)即可,然而目標(biāo)zval屬于引用變量,單純的增加引用計(jì)數(shù)顯然是錯(cuò)誤的, Zend的解決辦法是為d單獨(dú)生成一份zval副本。
全過程如下所示:

1.1.5 參數(shù)傳遞
php函數(shù)參數(shù)的傳遞和變量賦值是一樣的,非引用傳遞相當(dāng)于非引用賦值,引用傳遞相當(dāng)于引用賦值,并且也有可能會導(dǎo)致執(zhí)行zval狀態(tài)切換。這在后面還將提到。

php技術(shù)深入PHP變量存儲的詳解,轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 一区精品视频在线观看 | 亚洲精品久| 国产成人精品高清久久 | 在线一级片| 成人免费大片黄在线播放 | 毛片在线看片 | 成年免费大片黄在线观看岛国 | 精品福利一区二区三区 | 国产.com| 精品av久久久久电影 | 成人免费在线观看视频 | 婷婷色国产偷v国产偷v小说 | 综合精品在线 | 一级黄色网页 | 情侣酒店偷拍一区二区在线播放 | 99久久精品国产麻豆演员表 | 美女在线视频一区二区三区 | 婷婷成人在线 | 欧美1级 | 成人免费一区二区三区视频网站 | 亚洲精品99 | 三级av在线| 日韩中文字幕视频 | 国产视频久久 | 日韩欧美中文字幕在线视频 | 91精品一区二区三区久久久久久 | 97精品久久 | 日韩手机在线看片 | 天天躁日日躁狠狠的躁天龙影院 | 美女视频一区 | www.久久| 黄网免费 | 精品真实国产乱文在线 | 中文字幕av一区二区三区 | 日韩在线视频免费观看 | 激情六月丁香婷婷 | 午夜视频一区二区 | 精品视频免费 | 久在线| 欧美中文字幕在线观看 | 亚洲人成在线播放 |