1,引用的基本概念
$a = array(1, 2, 3);
foreach ($a as &$value) { // 注意这里使用了 &
$value *= 2;
}
// 这时 $value 仍然是一个引用,指向数组的最后一个元素
2,常见的陷阱情况
$a = array(1, 2, 3);
// 第一个循环
foreach ($a as &$value) { // 使用引用
$value *= 2;
}
// 此时 $value 仍然引用着 $a 的最后一个元素
// 第二个循环
foreach ($a as $value) { // 没有使用引用,但 $value 仍然是上一个循环的引用
// 这里会出问题,因为每次赋值都会修改原数组的最后一个元素
}
3,为什么会发生
当使用 & 引用时,$value 变量会直接指向数组元素的内存位置
循环结束后,这个引用关系不会自动解除
如果后续再次使用这个变量(即使是在新的循环中),它仍然保持着引用关系
这就导致在后续操作中可能意外修改原数组的值
4,预防措施
// 方法1:使用完引用后立即解除
foreach ($array as &$value) {
// 处理
}
unset($value); // 重要!
// 方法2:避免使用引用,使用键值
foreach ($array as $key => $value) {
$array[$key] = $value * 2;
}
// 方法3:使用普通for循环
for ($i = 0; $i < count($array); $i++) {
// 处理
}
// 方法4:如果必须使用引用,创建数组副本
$array_copy = array_map(function($item) {
return $item;
}, $array);
5,最佳实践
除非必要,尽量避免在 foreach 中使用引用
如果使用了引用,在循环结束后立即 unset 引用变量
对于需要修改数组元素的情况,优先考虑使用键值方式
如果不确定是否存在引用问题,使用 for 循环会更安全
记住这个口诀:
"用了引用要解除"
"不确定就用 for"
"改数组用键值"
这样在日后的编程中就能避免这类问题了。