PHP写时分离与写时改变

    首先要明确PHP是弱类型语言,所谓的弱类型就是说一开始并不严格规定变量的数据类型,因为PHP可以进行数据类型的转换。也就是说,在PHP中,一个变量可以保存为任何的数据类型

    然后我们开始认识PHP变量中的结构体:zval(这里我们称为“变量容器”)。

struct _zval_struct {
    /* Variable information */
    zvalue_value value;  /* 变量值保存在这里 12字节*/
    zend_uint refcount;//4字节,变量引用计数器
    zend_uchar type;   /* active type变量类型 1字节*/
    zend_uchar is_ref;//是否变量被&引用,0表示非引用,1表示引用,1字节
};
  • zvalue_value value:用来保存变量的值。
  • zend_unit refcount:用来保存有多少个变量指向这个zval,实际是一个计数器。初始变量时,recount的值为1,赋值操作例如$a = $b会使refcount+1,而unset就会令其-1。当refcount=0时,php会认为这个zval是垃圾,就被回收了,释放该zval所占的内存空间。PHP5.3之后引入新的垃圾回收机制,避免因循环引用导致的内存泄露。
  • zend_uchar type:用来保存变量的数据类型。4种标量(int、float、string、bool),2种复合(array、object),2种特殊(resource、null)。
  • zend_uchar is_ref:用来标记变量是否为引用变量。只有0和1两种表示,0表示普通变量,1表示引用变量。

好了,我们先来看看例子吧:

一、写时分离

$a = 1;
$b = $a;
$c = $b;
$d = &$c; // 在一堆非引用赋值中,插入一个引用

二、写时改变

$a = 1;
$b = &$a;
$c = &$b;
$d = $c; // 在一堆引用赋值中,插入一个非引用

三、结论

  1. php在修改一个变量之前,会先检查这个变量的refcount是否大于1,如果大于1,则执行分离的过程。
  2. 分离:分离两个变量存储的zval的位置,让分开的变量不指向同一个空间。
  3. 改变:有&引用赋值时,要把新开辟的zval 的 is_ref 赋值为1。
  4. 判定是否分离的条件:如果is_ref =1 或recount == 1,则不分离。

四、注意

数组变量和普通变量生成的zval不同,在循环引用时容易导致内存泄漏,如$a[] = &$a,此时这个zval中的refcount=2,当我们unset($a)后,refcount=1,但是$a已经被销毁,却还存在$a[]指向这个zval,这样就占着内存释放不了导致内存泄漏。

PHP5.3之后引入新的垃圾回收机制避免这种情况发生,官方具体文档:http://php.net/manual/zh/features.gc.php

 

转载:https://blog.csdn.net/ty_hf/article/details/51057954

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值