• PHP7引用类型


    php5在引入引用计数后,使用了refcount_gc来记录次数,同时使用is_ref_gc来记录是否是引用类型。

    例如

    $a = 'hello';

    //$a->zval1(type=IS_STRING,refcount_gc=1,is_ref_gc=0)

    这个时候$a指向一个结构体,主要看refcount_gc=1,这就是引用计数字段,因为hello这个字符串被赋值给了$a,所以这个时候hello的引用计数就是1

    $b = $a;

    $b,$a->zval1(type=IS_STRING,refcount_gc=2,is_ref_gc=0)

    这个时候又把$a赋值给了$b,所以这个时候$b和$a同时指向这个结构体,并且引用计数加1

    $c = &$b;

    //$a->zval1(type=IS_STRING,refcount_gc=1,is_ref_gc=0)

    //$c,$b->zval2(type=IS_STRING,refcount_gc=2,is_ref_gc=1)

    这个时候因为把$b赋值给了$c,但是是传址的方式,所以在这个时候就要分离了,$a还指向原来的结构体,$c和$b同时指向一个新的结构体,这个时候zval的is_ref_gc值会改变,使得此时的zval必须进行分离,但是实际上他们的值还没有变化,这使得需要在堆中维护两个值为"hello"的zval。

    下面我们来看看php7中的实现

    php7引入了新的类型IS_REFERENCE来处理这个问题,首先看看zend_reference的结构体:

    struct _zend_reference{

    zend_refcounted_h gc;

    zval val;

    };

    $a = 'hello';

    //$a->zend_string(refcount=1,val)

    $b = $a;

    //$b,$a->zend_string(refcount=2,val)

    $c = &$b;

    //$a->zend_string(refcount=2,val)

    //$c,$b->zval(type=IS_REFERENCE,refcount=2)->zend_string(refcount=2,val)

    从上面可以看出来,当使用&操作时,会创建一种新的中间结构体zend_referenct,这个结构体会指向真正的zend_string结构体,所以zend_string结构体的引用计数不变,同时zend_reference结构体的引用计数变为2,因为$c和$b此时的类型都会变为zend_reference,这样的好处是原始的zend_string在内存中始终只有一份(避免了由于字符串的重复申请导致的内存浪费),更加易于维护。

  • 相关阅读:
    C++11 特色语法在 OI 中的运用
    webpack基本使用(一)
    LeetCode 887. 鸡蛋掉落 题解
    Codeforces Round #735 (Div. 2) C. Mikasa
    阿里云RDS与ECS自建mysql数据库主从同步(GTID方式)
    MySQL 5.7.x修改root默认密码
    SpringBoot引入第三方jar包或本地jar包的处理方式
    K8s 常用命令(随时更新......)
    六 Prometheus + Altermanager Email 报警
    四 Prometheus + consul
  • 原文地址:https://www.cnblogs.com/wenxinphp/p/12640689.html
Copyright © 2020-2023  润新知