【问题标题】:What happens behind the scene of PHPs foreach?PHP foreach 的幕后发生了什么?
【发布时间】:2019-06-05 03:45:09
【问题描述】:

PHP 7.1 中的实验(docker image nanoninja/php-fpm:7.1)

在下一段代码中一切都清楚了:

$arr1 = [1, 2, 3];

foreach ($arr1 as &$value) {
    $value *= 2;
}

我们有数组 $arr1 并将所有值乘以 2。结果:

array(3) {
  [0]=>
  int(2)
  [1]=>
  int(4)
  [2]=>
  &int(6)
}

但是在这个语句中会发生什么:

$arr1 = [1, 2, 3];

foreach ($arr2 = $arr1 as &$value) {
    $value *= 2;
}

$arr1$arr2 两个数组的结果将不可更改:

array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}

为什么会这样?我知道在 PHP > 7 foreach 中适用于数组的副本,但在这种情况下适用于哪个数组的副本 $arr1$arr2。为什么& 不起作用?

【问题讨论】:

  • 你能做一个这样的内联声明并在同一个地方传递一个变量作为引用吗?在这种情况下,for each 会使用哪个?
  • @Dharman 这不是关于 foreach 的工作原理,而是赋值表达式本身返回一个值。
  • foreach ($arr2 = $arr1 as ... 等价于 foreach (function() as ... - 在这两种情况下,迭代器都会循环遍历操作后丢弃的临时数组

标签: php arrays foreach php-7.1


【解决方案1】:

foreach 仅适用于普通按值模式下的数组副本,不适用于按引用模式。因此 PHP 7 中的更改与此代码无关。

但是在您的第二个代码块中,您没有使用变量作为数组进行迭代,因此没有什么可以引用的。相反,您有一个表达式,表达式的值是数组的副本。它本质上相当于做:

$temp = $array1 = $array2;
foreach ($temp as &$value) {
    $value *= 2;
}

这将更新$temp,但不会更新$array1$array2

【讨论】:

  • 如果有人对操作码详细信息感兴趣,请参阅 vld 转储here。第二个ASSIGN,使用操作数!1, !0(分别为$arr2$arr1)返回$4(赋值表达式的值),然后由FE_RESET_RW操作码使用(基本上启动foreach .) 与直接使用!0 ($arr1) 的this one 进行比较。
猜你喜欢
  • 1970-01-01
  • 2011-10-19
  • 1970-01-01
  • 2011-07-12
  • 1970-01-01
  • 2018-03-29
  • 1970-01-01
  • 2010-09-06
  • 2018-12-05
相关资源
最近更新 更多