typedef struct zval_struct{
zval_value value;
zend_uint ref_count;
zend_uchar type;
zend_uchar is_ref;
}
其中是真正保存数据的部分,定位为一个联合体(union)
typedef union _zvalue_value {
long lval;
double dval;
struct {
char *val;
int len;
} str;
HashTable *ht;
zend_object_value obj;
} zvalue_value;
写时复制
$a = 1;
$b = $a;
$b += 5;
- 复制一个和
$b
所指向zval
一样的zavl
; - 将
$b
所指的zval
的ref_count
减一; - 初始化新的
zval
设置ref_count=1
,is_ref=0
; - 让
$b
指向新的zval
写时改变
$a = 1;
$b = &$a;
$b += 5;
- 第一步和写时复制的第一步一样;
- 第二步
$b
所指向的zval
的ref_count+1
,并将is_ref
设置为1; $b
变化时,会执行get_var_and_separate()
函数看是否需要分离,如果is_ref
会直接返回$b
所指向的zval
- 再去修改
$b
的值,$a
的值也会变,因为指向的都是同一个zval
写时分离
$a = 1;
$b = $a;
$c = &$a;
如果一个zval
结构体既有ref_count
和is_ref
Zend
会将等号右边的变量分离出来一个新的zval
global
和$_GOLBAL['a']
-
global
是全局作用域a
的引用 -
$_GOLBAL['a']
是全局作用域a
的本身