zoukankan      html  css  js  c++  java
  • PHP 引用变量

    1、引用变量的定义

    在PHP 中引用的意思是:不同的名字访问同一个变量内容.使用&表示

    使用 & 会使(如$a = &$b)指向同一个内存地址(这并不像 C 的指针:例如你不能对他们做指针运算,他们并不是实际的内存地址),一个发生改变,另一个也会发生改变

    2、使用 memory_get_usage() 函数观察内存的变化

    2.1、不使用 &

    因为PHP 中COW(Copy On  Write) 会导致赋值是引用上一个变量的地址(内存不会发生太大变化),只有在发生 写 操作的时候,才会开辟新的内存地址

    $a = range(0,1000);
    var_dump(memory_get_usage());
    
    $b = $a;
    var_dump(memory_get_usage());
    
    $a = range(0,1000);
    var_dump(memory_get_usage());
    运行结果:

    内存在第一次和第二次并没有太大的差异,第三次产生较大差异

    2.2、使用 & 

    $a = range(0,1000);
    var_dump(memory_get_usage());
    
    $b = &$a;
    var_dump(memory_get_usage());
    
    $a = range(0,1000);
    var_dump(memory_get_usage());

    运行结果:

    内存在过程中基本没有发生变化,虽然第三步进行了写操作,但是 $a,$b引用的同一个地址,就不需要开辟新地址

    3、使用xdebug 观察

    xdebug 的安装方法 网上很多,这里不细讲(php 的一个扩展插件而已)

    3.1、不使用 &

    //zval 变量容器
    $a = range(0, 3);
    xdebug_debug_zval('a');
    
    //定义变量b,把a的值赋值给b
    $b = $a;
    xdebug_debug_zval('a');
    //修改a
    $a = range(0, 3);
    xdebug_debug_zval('a');

    运行如下:

    refcount用以标识指向这个zval变量容器的变量个数

    is_ref(bool),标识此变量是否属于引用集合

    第二步只进行了COPY 操作,使$a , $b 指向同一个内存地址, refcount = 2,而第三步 发生了写操作(is_ref=0 不是引用),重新开辟了内存地址,refcount= 1

    3.2、使用 &

    //zval 变量容器
    $a = range(0, 3);
    xdebug_debug_zval('a');
    
    //定义变量b,把a的值赋值给b
    $b = &$a;
    xdebug_debug_zval('a');
    
    //修改a
    $a = range(0, 3);
    xdebug_debug_zval('a');

    运行结果:

    采用了 引用(&),所以 从第二步开始 refcount = 2,is_ref = 1(引用) ,引用状态下不开辟新的内存地址;

    4、特殊的引用(对象)

    php 中 OBJECT 本身就是引用传值(自 PHP 5 起,new 自动返回引用,因此在此使用 =& 已经过时了并且会产生 E_STRICT 级别的消息。)

    //对象本身就是引用传递
    class Person 
    {
        public $name = 'zs';
    }
    $p1 = new Person;
    xdebug_debug_zval('p1');
    
    $p2 = $p1;
    xdebug_debug_zval('p1');
    
    $p2->name = 'ls';
    xdebug_debug_zval('p1');

    运行结果:

    OBJECT 赋值情况下 会共享内存地址,但本身又不是引用。

    5、unset

    //unset 只会取消引用,不会销毁空间
    $a = '';
    xdebug_debug_zval('a');
    $b = &$a;
    xdebug_debug_zval('a');
    unset($b);
    xdebug_debug_zval('a');

    运行结果:

    所以在第一步的时候  refcount = 0 

    对应 引用(&),unset只会取消引用,而不会销毁内存地址

    5、总结

    通过对 is_ref 判断是否是引用变量,如果是引用变量,修改时直接修改(原内存地址),否则,则需要进行 分离(重新开辟新地址),而  usset 变量只是取消该变量的引用,而不会消除内存地址,只有当refcount = 0;内存才有可能被回收

  • 相关阅读:
    负载均衡--hash slot算法
    redis cluster slots数量 为何是16384(2的14次方)
    ZooKeeper原理与它的集群工作流程
    5分钟入门chrony
    微服务的下一步,离不开服务网格
    sar统计日流量与实时流量
    docker查看jvm内存占用
    k8s编排
    Rsync 排除文件
    Kubernetes 中优雅停机和零宕机部署
  • 原文地址:https://www.cnblogs.com/ImCehnyx/p/7816399.html
Copyright © 2011-2022 走看看