php数组底层采用,PHP底层原理分析(二):写时复制和强制分裂

摘要:学习需要知其然而知其所以然,PHP底层相关就是这类知识,从上文中知道声明一个变量,将会产生一个结构体,那么在传值赋值和引用赋值时, 结构体是如何变化的呢?

从上文(http://blog.yzmcms.com/html/php/173.html) 中知道声明一个变量,将会产生一个结构体,那么在传值赋值和引用赋值时, 结构体是如何变化的呢?

一、变量的传值赋值:

以: $a = 3 ; $b = $a为例,此时并没有再次产生结构体,而是2个变量共用1个结构体,refcount__gc 值为2。

$a = 3

此时的结构体:{

value:3

type:IS_LONG

refcount__gc:1

is_ref__gc:0

}

$b = $a;

此时$a和$b共用一个结构体:{

value:3

type:IS_LONG

refcount__gc:2

is_ref__gc:0

}

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

答: 不会,

因为两者,有一方修改时,将会造成结构体的分裂。

$b = 5; //此时修改变量的值

结构体如下:

$a的结构体是:{

value:3

type:IS_LONG

refcount__gc:1

is_ref__gc:0

}

$b的结构体是:{

value:5

type:IS_LONG

refcount__gc:1

is_ref__gc:0

}

结构体一开始共用,到某一方要修改值时,才分裂。这种特点称为Copy-on-Write,也就是写时复制。

二、变量的引用赋值:

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

$a = 1;

此时的结构体:{

value:1

type:IS_LONG

refcount__gc:1

is_ref__gc:0

}

$b = &$a;

此时$a和$b共用一个结构体:{

value:1

type:IS_LONG

refcount__gc:2

is_ref__gc:1

}

is_ref__gc:1表示引用赋值,此时,如果修改$a和$b任意一个值,结构体不会分裂,$a和$b两个值也将都会修改;

三、强制分裂:

那么现在有这样一个代码:$a = 3;

$b = $a;

$c = &$a;

$c = 5;

echo $a.$b.$c; //535

为什么会是这样的结果呢,这跟上面我们讲的结构体不一样呢?

原因就是此时发生了强制分裂!

当is_ref__gc[引用属性]从0->1,如果refcount__gc>1,那么就会发生强制分裂。

这个就是强制分裂。原本已经经过传值赋值的变量,再次引用赋值出去。被传值赋值的变量就会被分裂出一个结构体,简单可以理解为:在引用变量主动赋值前,该变量传值赋值过,就会发生强制分裂。

上述代码中:

$b强制分裂出一个结构体:{

value:3

type:IS_LONG

refcount__gc:1

is_ref__gc:0

}

$a个$c共用一个结构体:{

value:5

type:IS_LONG

refcount__gc:2

is_ref__gc:1

}

注意:在数组中慎用引用赋值,例如:$arr = array(0,1,2,3);

$x = &$arr[1];

$tem = $arr;

$arr[1] = 999;

echo $tem[1];

//结果为 999

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值