亚洲精品中文字幕无乱码_久久亚洲精品无码AV大片_最新国产免费Av网址_国产精品3级片

php語(yǔ)言

深入PHP變量存儲(chǔ)的詳解

時(shí)間:2024-08-13 02:00:00 php語(yǔ)言 我要投稿
  • 相關(guān)推薦

深入PHP變量存儲(chǔ)的詳解

  文章是對(duì)PHP變量的存儲(chǔ)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下,就跟隨百分網(wǎng)小編一起去了解下吧,想了解更多相關(guān)信息請(qǐng)持續(xù)關(guān)注我們應(yīng)屆畢業(yè)生考試網(wǎng)!

  1.1.1 zval結(jié)構(gòu)

  Zend使用zval結(jié)構(gòu)來(lái)存儲(chǔ)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值來(lái)決定訪問(wèn)value的哪個(gè)成員,可用值如下:

  IS_NULL

  N/A

  IS_LONG

  對(duì)應(yīng)value.lval

  IS_DOUBLE

  對(duì)應(yīng)value.dval

  IS_STRING

  對(duì)應(yīng)value.str

  IS_ARRAY

  對(duì)應(yīng)value.ht

  IS_OBJECT

  對(duì)應(yīng)value.obj

  IS_BOOL

  對(duì)應(yīng)value.lval.

  IS_RESOURCE

  對(duì)應(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變量可以通過(guò)引用計(jì)數(shù)機(jī)制來(lái)共享同一份zval,zval中剩余的兩個(gè)成員is_ref和refcount就用來(lái)支持這種共享。

  很明顯,refcount用于計(jì)數(shù),當(dāng)增減引用時(shí),這個(gè)值也相應(yīng)的遞增和遞減,一旦減到零,Zend就會(huì)回收該zval。

  那么is_ref呢?

  1.1.3 zval狀態(tài)

  在PHP中,變量有兩種——引用和非引用的,它們?cè)赯end中都是采用引用計(jì)數(shù)的方式存儲(chǔ)的。對(duì)于非引用型變量,要求變量間互不相干,修改一個(gè)變量時(shí),不能影響到其他變量,采用Copy-On-Write機(jī)制即可解決這種沖突——當(dāng)試圖寫(xiě)入一個(gè)變量時(shí),Zend若發(fā)現(xiàn)該變量指向的zval被多個(gè)變量共享,則為其復(fù)制一份refcount為1的zval,并遞減原zval的refcount,這個(gè)過(guò)程稱為“zval分離”。然而,對(duì)于引用型變量,其要求和非引用型相反,引用賦值的變量間必須是捆綁的,修改一個(gè)變量就修改了所有捆綁變量。

  可見(jiàn),有必要指出當(dāng)前zval的狀態(tài),以分別應(yīng)對(duì)這兩種情況,is_ref就是這個(gè)目的,它指出了當(dāng)前所有指向該zval的變量是否是采用引用賦值的——要么全是引用,要么全不是。此時(shí)再修改一個(gè)變量,只有當(dāng)發(fā)現(xiàn)其zval的is_ref為0,即非引用時(shí),Zend才會(huì)執(zhí)行Copy-On-Write。

  1.1.4 zval狀態(tài)切換

  當(dāng)在一個(gè)zval上進(jìn)行的所有賦值操作都是引用或者都是非引用時(shí),一個(gè)is_ref就足夠應(yīng)付了。然而,世界總不會(huì)那么美好,PHP無(wú)法對(duì)用戶進(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;之后是兩次非引用賦值,正如前面所說(shuō),只要把b和c都指向a的zval即可;最后一行是個(gè)引用賦值,需要is_ref為1,但是Zend發(fā)現(xiàn)c指向的zval并不是引用型的,于是為c創(chuàng)建單獨(dú)的zval,并同時(shí)將d指向該zval。

  從本質(zhì)上來(lái)說(shuō),這也可以看作是一種Copy-On-Write,不僅僅是value,is_ref也是受保護(hù)的對(duì)象。

  整個(gè)過(guò)程圖示如下:

  情況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副本。

  全過(guò)程如下所示:

  1.1.5 參數(shù)傳遞

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

【深入PHP變量存儲(chǔ)的詳解】相關(guān)文章:

PHP數(shù)據(jù)類型之?dāng)?shù)組變量詳解10-04

PHP的變量09-10

什么是PHP的變量07-29

PHP的變量介紹11-07

PHP變量介紹02-28

C語(yǔ)言變量存儲(chǔ)布局07-05

原創(chuàng)PHP教程:變量10-22

PHP的變量是什么06-10

php靜態(tài)成員變量06-22

php變量定義方法08-12