传值赋值发生了什么

变量的赋值与引用:

注意:

在传值赋值时

: $a = 3 ; $b = $a为例,

并没有再次产生结构体,而是2个变量共用1个结构体.

此时,2个变量,指向同1个结构体,

refcount_gc 值为2



思考: a, b指向同一个结构体那么,修改a,b ,对方会不会受干扰?

不会,

因为2,有一方修改时,将会造成结构体的分裂.

结构体一开始共用到某一方要修改值时,才分裂

这种特点,称为cow , copy on write ,




当引用赋值时, 双方共用一个结构体(is_ref_gc=1)

发生如下图的变化


强制分裂:

$a = 3;

底层结构体如下:

/**

{

  value : 3

  refcount_gc : 1

  is_ref_gc : 0

**/

$b = $a;

/**

  value : 3

  refcount_gc :2

  is_ref_gc : 0

**/


$c = &a;

/**

//如果is_ref_gc 从0->1的过程中,refcount_gc>1时,将会强制分裂


b分裂一份结构体

{

  value : 3

  refcount_gc : 1

  is_ref_gc : 0

}

a,c

{

  value : 3

  refcount_gc : 2

  is_ref_gc : 1

}

**/


引用数组时的怪现象:

$arr = array(0,1,2,3);

$tmp = $arr;

$arr[1] = 11;

echo $tmp[1];//1

//此时$arr和$tmp公用一个哈希表(用来存放数组数据)

图解:

图一:

当$arr初始化时,底层会生成一个哈希表来存放数组里面的值

当执行$tmp = $arr时,$tmp中的zvalue指向了$arr的哈希表

图2:

当执行$arr[1] = 11时,底层进行并没有强制分裂($tmp中下标为1的此时进行了分裂),而是将$tmp的下标为1指向新分裂的结构体, 而 下标为0,2,3都是指向原来$arr哈希表里面的值


$arr = array(0,1,2,3);

$x = &$arr[1];

$tmp = $arr;


$arr[1] = 999;

echo $tmp[1];//999

这是PHP一个BUG,当执行$x = &$arr[1]时,PHP将哈希表中的$arr中的值为1的is_ref_gc修改为1,然后执行$tmp = $arr时,PHP将$tmp直接指向$arr的哈希表(其中包含了地址赋值的内容,这个地方并没有进行分裂


循环数组时的怪现象:

//引用时的一些怪现象

$arr = array(0,1,2,3);

foreach( $arr as $v) {

}

var_dump(current($arr)); //最后数组指针停留在数组结尾,取不到值,输出false


$arr = array(0,1,2,3);

foreach( $arr as $k => $v) {

  $arr[$k] = $v;

}

var_dump(current($arr)); //输出1

注意:$arr跟$arr(copy即foreach中的$arr)的关系是赋值关系

var_dump(current($arr)); //输出1,在foreach循环中,$arr是上面的$arr的一个copy数据,因为当执行foreach的第一步时,PHP读取$arr(copy)数组中的第一个值,然后将指针下移到下一个值中(注意:这里是先读取指针指向的值,然后才将指针移动到下一个地址),然后第一次执行$arr[$k] = $v的赋值操作时,$arr跟$arr(copy)要进行分裂,原来的$arr指针只是移动了一个位置,然后就不移动了


$arr = array(1,2,3);

foreach( $arr as &$v) {

}

//上面的foreach等价于$v = &$arr[2]

foreach ( $arr as $v) {

 print_r($arr);

}

输出:

121

122

122

原因:第一个foreach将数组的最后一个元素的地址赋值给$v,然后第二个foreach中,每次循环都将数组最后一个元素的值修改了


提醒:

1.使用数组时,慎用地址引用

2.foreach使用后,不会把数组内部的指针重置,需要使用reset


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值