You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP中数组引用赋值后再次赋值未复制数组的问题咨询

为什么PHP中$b = $a没有创建数组副本,反而修改$b时$a同步变化?

先还原你的代码场景:

$a = [1,2]; 
$b = &$a; // $b holds reference to $a 
$b[] = 3; // so this makes $a to {1,2,3} 
$b = $a; // $b now holds COPY of $a (not reference) - 这是你的预期,但实际不符
$b[] = 4; // so $a must be the same {1,2,3} 
var_dump($a); // but it isn't - $a is {1,2,3,4} 

这是PHP引用机制里非常典型的误区,咱们一步步拆解每一步的变量状态,就能搞清楚问题根源:

  1. 初始化数组
    $a = [1,2];
    此时$a指向一个数组对象,这个数组的**引用计数(refcount)**是1,且没有被标记为引用(is_ref为false)。

  2. 创建引用关系
    $b = &$a;
    现在$b成为$a的别名——它们本质上是同一个变量,共享同一个数组对象。此时数组的refcount变为2,is_ref被标记为true(因为存在活跃的引用关系)。

  3. 通过引用修改数组
    $b[] = 3;
    因为$b是$a的引用,修改$b就是直接修改共享的数组,所以$a同步变成[1,2,3],这部分符合你的预期。

  4. 关键误解:赋值操作的实际行为
    $b = $a;
    你以为这行代码会给$a创建副本并赋值给$b,从而断开引用,但实际不是!
    因为$b当前是$a的引用,这行代码等价于把$a的值(也就是那个数组)赋给$a自己。PHP处理这种“给自己赋值”的操作时,不会创建任何副本——它只会把数组的is_ref标记改为false(此时不再需要维持引用标记),但$b和$a仍然指向同一个数组对象,refcount降回1。

  5. 修改$b同步影响$a
    $b[] =4;
    现在数组的refcount是1,is_ref是false,属于普通数组变量操作,直接修改数组内容即可,不会触发写时复制(COW)。所以$b修改的还是$a指向的同一个数组,$a自然也会变成[1,2,3,4]。

如何实现你的预期?

如果你想让$b成为$a的独立副本,需要先解除$b和$a的引用关系,再赋值:

$a = [1,2]; 
$b = &$a; 
$b[] = 3; 
unset($b); // 解除$b和$a的引用绑定
$b = $a; // 此时才会创建$a的副本赋值给$b
$b[] = 4; 
var_dump($a); // 输出: array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) }

或者用array_values()强制生成数组副本,跳过解除引用的步骤:

$b = array_values($a); // 直接生成新的数组副本

这样后续修改$b就不会影响$a了。

内容的提问来源于stack exchange,提问作者Agnius Vasiliauskas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:58:34