php 赋值原理详解



1 (在右边木有& 符号的情况下) 先看左值 是否是引用 若是 直接将右值赋值给左变量。。左边引用计数不变

$a = 1;
$b = &$a;


$d = 2;
$e = &$d;


$b = $e;//输出 2 2 $b=&$e 输出 2 1
echo $b.PHP_EOL;
echo $a.PHP_EOL;

2 左值不是引用,且计数ref_count=1 

       左值==右值 则左值 经历一次减一 加一操作($a=&$a 则同时会设置is_ref=1)

      左值!= 右值 则看右值 有无& 符号(注意有无此符号 和 此值 是否已经是 引用 并无直接关系。。如果右值 不是引用类型变量  此符号会将右值is_ref=1)

                    若无    且右值非引用变量(is_ref=0) 则将右值引用加一 左值销毁 否则 销毁左值 使用右变量值(is_ref=1)重新初始化生成一个ref_count=1的变量

                                (这里右变量是is_ref=1 则提前初始化一个新的左值)

                    若有 则将右值的ref_count+1  左值销毁  返回右值 (例如 $b = 1;&$b; $a=&b, 则a和b都是is_ref=1的变量)

                                 

 3 左值ref_count>1 则减一即可 其他逻辑与2类似


来源php 内核深入理解


注意foreach($arr as $key=>&$val) 这来$val是引用 和 $a = &$b (a是引用) 注意这里区别

function a(&$a) {} ;

a($a);//已经是引用调用 a(&$a) 已经过 和赋值原理类似  这里和foreach 数组引用赋值类似 表示引用声明

php函数传递引用有运行时的引用和定义时引用的区别http://www.cunmou.com/phpbook/6.2.md

若一个函数 需要一个值类型大数组 硬是传递一个引用类型的 则传参时会发生大量的参数赋值过程 浪费时间


因为ZE2中所有的对象在当作函数参数的时候都是默认以引用的形式传递的。但是我们又必须把这个参数设置为数字1,除非你不想让你的扩展与PHP4兼容。在PHP4中,对象是传递的一个完整Copy,而非通过引用

对象默认的赋值操作时浅拷贝  数组是深度拷贝 即时clone 对象也只是里面的 值类型数据是拷贝http://www.cunmou.com/phpbook/7.2.md

<?php
//关于PHP语言中引用形式返回值的详述,请参考PHP手册。
$a = 'china';
 
function &return_by_ref()
{
    global $a;
    return $a;
}
 
$b = &return_by_ref();
$b = "php";
echo $a;
//此时程序输出php
</php>
在上面的代码中,$b其实是$a的一个引用,当最后一行代码执行后,$a和$b都开始寻找‘bar’这个字符串对应的zval,让我们以内核的角度重新观察这一切:
<code c>
#if (PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0)
ZEND_FUNCTION(return_by_ref)
{
    zval **a_ptr;
    zval *a;
     
    //检查全局作用域中是否有$a这个变量,如果没有则添加一个
    //在内核中真的是可以胡作非为啊,:-)
    if(zend_hash_find(&EG(symbol_table) , "a",sizeof("a"),(void **)&a_ptr ) == SUCCESS )
    {
        a = *a_ptr;
    }
    else
    {
        ALLOC_INIT_ZVAL(a);
        zend_hash_add(&EG(symbol_table), "a", sizeof("a"), &a,sizeof(zval*), NULL);
    }
     
    //废弃return_value,使用return_value_ptr来接替它的工作
    zval_ptr_dtor(return_value_ptr);
    if( !a->is_ref__gc && a->refcount__gc > 1 )
    {
        zval *tmp;
        MAKE_STD_ZVAL(tmp);
        *tmp = *a;
        zval_copy_ctor(tmp);
        tmp->is_ref__gc = 0;
        tmp->refcount__gc = 1;
        zend_hash_update(&EG(symbol_table), "a", sizeof("a"), &tmp,sizeof(zval*), NULL);
        a = tmp;
    }
    a->is_ref__gc = 1;
    a->refcount__gc++;
    *return_value_ptr = a;
}
#endif /* PHP >= 5.1.0 */


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值