php中foreach循环中键值使用&的问题

php中文网
发布: 2016-08-04 09:19:49
原创
1724人浏览过

代码如下:

<code>$a = [1, 2, 3];
foreach($a as $key => &$value) {
    $value = 5;
}
var_dump($a);</code>
登录后复制

最后输出结果如下:

立即学习PHP免费学习笔记(深入)”;

<code>array(3) { [0]=> int(5) [1]=> int(5) [2]=> &int(5) }</code>
登录后复制

问题:为什么会在最后的键值前出现取地址符?

回复内容:

代码如下:

<code>$a = [1, 2, 3];
foreach($a as $key => &$value) {
    $value = 5;
}
var_dump($a);</code>
登录后复制

最后输出结果如下:

立即学习PHP免费学习笔记(深入)”;

<code>array(3) { [0]=> int(5) [1]=> int(5) [2]=> &int(5) }</code>
登录后复制

问题:为什么会在最后的键值前出现取地址符?

这个var_dump里出现的&代表你可以用一个其他的变量来改变它的值。
比如你这样

<code class="php">$b = &$a[0];
var_dump($a);</code>
登录后复制

这里打印的时候就会在第一个键值里出现&符号,表示你可以用其他变量($b)来更改它的值。

先来了解一下&的基本用法。

<code class="php">$b = $c = 1;
$a = &$b;
$a = 2;
echo "b=$b,c=$c\n";
$a = &$c;
$a = 100;
$a = 200;
echo "b=$b,c=$c\n";
unset($a);
$a = 500;
echo "b=$b,c=$c\n";</code>
登录后复制

上面$a指定成$b的引用之后,除非再次指定成其他引用,或者unset($a),否则改变$a就是改变对应的$b的值。

对于你这个foreach,也是同样的道理,你把循环单步拆开,就是这个样子:

<code class="php">$value = &$a[0];
$value = 5;
$value = &$a[1];
$value = 5;
$value = &$a[2];
$value = 5;</code>
登录后复制

循环运行到最后的时候,$value是$a[2]的引用,所以就相当于这么个形式:

<code class="php">$a[0] = 5;
$a[1] = 5;
$value = &$a[2];
$a[2] = 5;
var_dump($a);</code>
登录后复制

也就不难理解为什么var_dump会在最后的键值对上打印出一个&的符号了吧。


一般情况下这个不会导致什么大问题,只不过由于foreach的作用域问题,会导致在循环退出之后$value依旧可以使用,所以会出现一些匪夷所思的bug。

比如这样

<code class="php">$a = [1, 2, 3];
foreach($a as $key => &$value) {
    $value = $value+5;
}
var_dump($a); // [6,7,8]
foreach($a as $value){}
var_dump($a); // [6,7,7]</code>
登录后复制

加了一句空的foreach之后,反而导致$a变的不合理了,这个bug匪夷所思,原因也是因为那个空foreach里的$value是最上面那个&a[2]的引用。

那个空foreach相当于这样:

<code class="php">$value = &$a[2];
$value = $a[0];
$value = $a[1];
$value = $a[2];</code>
登录后复制

注意到了么,由于$value是$a[2]的引用,所以上面的改写一下就是这样:

<code class="php">$a[2] = $a[0];
$a[2] = $a[1];
$a[2] = $a[2];</code>
登录后复制

空foreach里在不停的改变$a[2],而由于$a[2]已经变成$a[1]的值了,所以$a[2] = $a[2];没有任何影响,值还是$a[1];

这种匪夷所思的bug是由于$value这个变量的作用域导致的,所以要么改个名,要么先把$value给unset掉。

<code class="php">$a = [1, 2, 3];
foreach($a as $key => &$value) {
    $value = $value+5;
}
var_dump($a);
// 要么unset
unset($value);
// 要么foreach里不要用上面同名的$value,改为$value2222
foreach($a as $value2222){}
var_dump($a);</code>
登录后复制

首先我想说,这是一个非常非常好的问题。我相信题主并不是分不清引用与非引用。
我先做了一下两个测试:

<code>$a = [1, 2, 3];
foreach($a as $key => &$value) {
    $value = 5;
}
foreach($a as $key => $value) {
    $value = 6;
}
var_dump($a);</code>
登录后复制

你猜输出是什么?

<code>array(3) {
  [0]=>  int(5)
  [1]=>  int(5)
  [2]=>  &int(6)
}</code>
登录后复制

另外一个测试是:

<code>$a = [1, 2, 3];
foreach($a as $key => &$value) {
    $value = 5;
}
foreach($a as $key => $value2) {
    $value2 = 6;
}
var_dump($a);</code>
登录后复制

这次的输出就看上去正常多了:

<code>array(3) {
  [0]=>  int(5)
  [1]=>  int(5)
  [2]=>  &int(5)
}</code>
登录后复制

所以说,这个问题应该是php全局变量的一个坑。

相关标签:
php
PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号