带有引用的 Foreach 导致数组的最后一个元素重复

Foreach with reference causing array's last element to repeat

我 运行 遇到了一个奇怪的问题,可以用这个片段重现它:

<?php

$arr = [];

for($i = 0; $i <= 3; $i++) {
    $arr[] = [
        $i
    ];
}

foreach ($arr as &$item) {
    $item[] = $item[0];
}

foreach ($arr as $item) {
    print_r($item);
}

它正在输出(注意最后一个元素已被其前一个元素的副本替换):

Array
(
    [0] => 0
    [1] => 0
)
Array
(
    [0] => 1
    [1] => 1
)
Array
(
    [0] => 2
    [1] => 2
)
Array
(
    [0] => 2
    [1] => 2
)

然而,这是预期的结果:

Array
(
    [0] => 0
    [1] => 0
)
Array
(
    [0] => 1
    [1] => 1
)
Array
(
    [0] => 2
    [1] => 2
)
Array
(
    [0] => 3
    [1] => 3
)

如果我使用 array_map 而不是第一个 foreach,它会起作用:

<?php

$arr = [];

for($i = 0; $i <= 3; $i++) {
    $arr[] = [
        $i
    ];
}

$arr = array_map(function ($item) {
    $item[] = $item[0];
    return $item;
}, $arr);

foreach ($arr as $item) {
    print_r($item);
}

在 PHP 8.0.0.

下测试

是什么导致了这种差异?是否缺少有关数组指针的内容?

$arr = [];

for($i = 0; $i <= 3; $i++) {
    $arr[] = [
        $i
    ];
} 
/** Output 
* $arr = [[0],[1],[2],[3]]
*/

在此 foreach 循环中,您只是选择项目的现有值并将其设置为引用项目的新索引

foreach ($arr as &$item) {
    $item[] = $item[0];
}

$item的类型是数组,$item[0]指的是它的0索引 $item[] 表示当前引用的项目内的新数组索引。

在您的第一个示例中,$item 变量在循环完成后仍保留对 $arr 的最后一个值的 引用

foreach ($arr as &$item) {
    $item[] = $item[0];
}

如果你使用 print_r(get_defined_vars()); 你可以看到数组中有一个名为 item

的键

foreach 末尾的 double 值的行为是 described here 并且建议使用 unset($item)

销毁指定的变量

您也可以使用不同的变量名。


使用array_map,回调得到一个按名称传递的函数参数,它绑定到函数作用域。

如果你 运行 print_r(get_defined_vars()); 在使用 array_map 之后你可以看到没有名为 item

的键