为何在foreach定义中直接赋值变量时,引用遍历不生效?
两段PHP代码结果不同的原因
第一段代码的执行逻辑
$z = [[1,2,3],[4,5,6]]; foreach($z as &$i) { $i[] = 6; } echo json_encode($z), "\n"; // 输出 [[1,2,3,6],[4,5,6,6]]
- 首先
$z被赋值为目标二维数组,此时$z直接指向内存中的这个数组实例。 - foreach遍历的是
$z本身,&$i取到的是原数组里每个子元素的引用。 - 执行
$i[] = 6时,本质是直接修改$z中的子数组,所以最终$z的内容会被改变。
第二段代码的执行逻辑
foreach($z = [[1,2,3],[4,5,6]] as &$i) { $i[] = 6; } echo json_encode($z), "\n"; // 输出 [[1,2,3],[4,5,6]]
- 这里的核心差异是:PHP的foreach在处理表达式(而非直接变量)作为遍历目标时,会先对表达式的结果创建一个临时数组副本,然后遍历这个副本。
- 虽然
$z = [[1,2,3],[4,5,6]]确实完成了赋值,$z指向原数组,但foreach实际遍历的是这个数组的临时副本。 - 循环里的
&$i指向的是临时副本里的子数组引用,修改的是临时副本的内容,和$z指向的原数组没有关联。循环结束后临时副本被销毁,所以$z的内容完全没被改动。
简单总结
- 直接遍历变量
$z:操作的是原数组本身,修改引用会同步改变原数组。 - 遍历赋值表达式的结果:foreach使用临时副本遍历,修改的是副本,原数组不受影响。
内容的提问来源于stack exchange,提问作者Carl Shiles
相关产品推荐
相关产品推荐

