先来看看下面这段代码:

1
2
3
4
5
6
7
$arr = [111, 222, 333];
foreach ( $arr as &$value ) {
var_dump($value);
}
foreach ( $arr as $value ) {
var_dump($value);
}

运行结果:

1
2
3
4
5
6
111
222
333
111
222
222

出现这种情况是因为在第一个foreach中,每次的循环都相当于:

$value = &$arr[$i]; // $i 是$arr的索引

第一个foreach完成后,$value并没有注销掉,到第二个foreach时,每次的循环都相当于:

$value = $arr[$i]; // $i 是$arr的索引

$value在第一个foreach中被定义为了一个引用值$value = &$arr[2],所以第二个foreach会更新$arr[2]的值。

所以,再次使用$value前需要unset($value);

手册说明

可以很容易地通过在 $value 之前加上 & 来修改数组的元素。此方法将以引用赋值而不是拷贝一个值。

1
2
3
4
5
6
$arr = array(1234);
foreach ($arr as &$value) {
$value = $value * 2;
}
// $arr is now array(2, 4, 6, 8)
unset($value); // 最后取消掉引用

$value 的引用仅在被遍历的数组可以被引用时才可用(例如是个变量)。以下代码则无法运行:

1
2
3
foreach (array(1234as &$value) {
$value = $value * 2;
}

Warning
数组最后一个元素的 $value 引用在 foreach 循环之后仍会保留。建议使用 unset() 来将其销毁。

Note:foreach 不支持用“@”来抑制错误信息的能力。