php foreach变量引用的问题

PHP中变量的作用域不像java, c中的那样有明确的限定。比如, 我们在一个php文件中有这样一段代码:

$data = ['a', 'b', 'c'];
//在foreach循环中建立了变量$key和$value
foreach ($data as $key => $value) {
    //do nothing here
}
//在foreach外面仍然可以访问这两个变量
var_dump($key);
var_dump($value);

在这个foreach循环中定义的变量$key$value, 在foreach外面也是可以访问的。上面代码的执行结果是:

int(2)
string(1) "c"

当然,如果这个foreach是在一个function内,那么在这个function外是不能直接访问这两个变量的。

例子

例1

看下面这个例子:

$data = ['a', 'b', 'c'];
foreach ($data as $key => $value) {
    $value = &$data[$key];//引用
}
print_r($data);

执行的结果是:

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

我们可以看到变量$data的值已经被改变了! 这很奇怪吧! 我们在循环中打印变量:

$data = ['a', 'b', 'c'];
foreach ($data as $key => $value) {
    $value = &$data[$key];//引用
    echo $key, ': ', $value, ' => ', json_encode($data) . PHP_EOL;
}

执行结果是:

0: a => ["a","b","c"]
1: b => ["b","b","c"]
2: c => ["b","c","c"]

我们可以看到:

  • 第一次循环时
    • 先把$data[0]赋给了变量$value
    • 随后又将变量$value变成了地址引用,指向$data[0]
  • 第二次循环时
    • 先把$data[1]赋给了变量$value,但是因为变量$value是指向$data[0]的,这导致$data[0]的值被修改为 b
    • 随后又将$value指向了$data[1]的地址
  • 第三次循环时
    • 先把$data[2]赋给了变量$value,但是因为变量$value是指向$data[1]的,这导致$data[1]的值被修改为 c
    • 随后又将$value指向了$data[2]的地址

如果在这个代码后面再修改一下$value的值, 数组$data会变成什么样呢?

$data = ['a', 'b', 'c'];
foreach ($data as $key => $value) {
    $value = &$data[$key];//引用
    echo $key, ': ', $value, ' => ', json_encode($data) . PHP_EOL;
}
foreach ($data as $key => $value) {
}
print_r($data);
//在这里修改$value的值, 然后在看看原来的数组变成了什么
$value = 120;
echo $value . PHP_EOL;
print_r($data);

执行结果是:

0: a => ["a","b","c"]
1: b => ["b","b","c"]
2: c => ["b","c","c"]
Array
(
    [0] => b
    [1] => c
    [2] => c
)
120
Array
(
    [0] => b
    [1] => c
    [2] => 120
)

我们可以看到, $data[2]的值变成了120,而这可能不是我们想要的!

例2

这是例子是参考手册上的:

$arr = [1, 2, 3, 4];
foreach ($arr as &$value) {
    $value = $value * 2;
}
echo '$arr 现在是 ' . json_encode($arr) . PHP_EOL;
// $arr 现在是 [2, 4, 6, 8]

// 前面没有unset掉, 所以这里 $value 仍然指向 $arr[3] 的地址
foreach ($arr as $key => $value) {
    // $arr[3] 的值会在每一次循环时被修改
    echo $key . ' => ' . $value . '  $arr 现在是 ' . json_encode($arr) . PHP_EOL;
}

执行结果是:

$arr 现在是 [2,4,6,8]
0 => 2  $arr 现在是 [2,4,6,2]
1 => 4  $arr 现在是 [2,4,6,4]
2 => 6  $arr 现在是 [2,4,6,6]
3 => 6  $arr 现在是 [2,4,6,6]

如何避免地址引用带来的问题?

  1. unset()来destroy掉变量
  2. 不用地址引用
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值