php+Zval

Zval 是 PHP 中最重要的数据结构之一(另一个比较重要的数据结构是 hash table),它包含了 PHP 中的变量值和类型的相关信息。

1,它是一个 struct,基本结构为
	struct _zval_struct {
		// 存储变量的值
	    zvalue_value value;
	    // 表示引用计数
	    zend_uint refcount__gc;
	    // 变量具体的类型
	    zend_uchar type;
	    // 表示是否为引用 
	    zend_uchar is_ref__gc;
	};
	typedef struct _zval_struct zval;

2,Zval 在内核中的工作
	$a = ['string' => 'life', 'object' => new stdClass()];
	xdebug_debug_zval('a');
	// a:(refcount = 1, is_ref = 0) = array('string' => (refcount = 1, is_ref = 0) = 'life', 'object' => (refcount = 1, is_ref = 0) = new stdClass());
	/**
	 * zval.value = array('string' => 'life', 'object' => new stdClass());
	 * zval.is_ref__gc = 0;
	 * zval.type = 'array';
	 * zval.refcount__gc = 1;
	 */
	 创建数组时,会创建一个 zval(与普通变量生成的 zval 非常类似,但也有很大不同,数组和对象这类复合型的变量在生成 zval 时,会为每个 key 项生成一个 zval 容器)


	$c = &$a['string'];
	xdebug_debug_zval('a');
	// a:(refcount = 1, is_ref = 0) = array('string' => (refcount = 2, is_ref = 1) = 'life', 'object' => (refcount = 1, is_ref = 0) = new stdClass());
	xdebug_debug_zval('c');
	// c:(refcount = 2, is_ref = 1) = 'life';
	数组引用给另一个变量时,会增加 zval 中 refcount 和 is_ref 值

	
	$b = $a['object'];
	xdebug_debug_zval('a');
	// a:(refcount = 1, is_ref = 0) = array('string' => (refcount = 2, is_ref = 1) = 'life', 'object' => (refcount = 2, is_ref = 0) = new stdClass());
	xdebug_debug_zval('b');
	// b:(refcount = 2, is_ref = 0) = new stdClass();
	数组赋值给另一个变量时,会增加 zval 中 refcount 值

	$d = $b;
	xdebug_debug_zval('b');
	// b:(refcount = 3, is_ref = 0) = new stdClass();
	xdebug_debug_zval('d');
	// d:(refcount = 3, is_ref = 0) = new stdClass();

	
	$c = 'new lift';
	xdebug_debug_zval('a');
	// a:(refcount = 1, is_ref = 0) = array('string' => (refcount = 2, is_ref = 1) = 'new lift', 'object' => (refcount = 2, is_ref = 0) = new stdClass());
	xdebug_debug_zval('c');
	// c:(refcount = 2, is_ref = 1) = 'new lift';
	以上 c 引用 a['string'] 的值属于使用共享 zval 的形式,当 c 改变时 refcount 和 is_ref 值不变唯有 a 和 c 的 value 值改变

	
	unset($c);
	xdebug_debug_zval('a');
	// a:(refcount = 1, is_ref = 0) = array('string' => (refcount = 1, is_ref = 0) = 'new lift', 'object' => (refcount = 2, is_ref = 0) = new stdClass());
	unset 时,对应减少 zval 中 refcount 和 is_ref 值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值