PHP foreach()里使用& 引用赋值

<?php
$data = ['a','b','c'];

foreach ($data as &$v) {

}

foreach ($data as $v) {

}

unset($v);

var_dump($data);

这段代码的结果如何推导?是什么原理?

阅读 7.8k
4 个回答

好像以前见过类似的问题...

<?php
/* 第一次遍历 */
$v = &$data[0];
$v = &$data[1];
$v = &$data[2];

// 第一次遍历完成后, 这个时候 $v = &$data[2]


/* 第二轮遍历 */
// 因为$v等价于$data[2],相当于$data[2] = $data[0],把$data[2]赋值为a(即$data[0]); 此时数组array = ['a','b','a'];
$v = $data[0]; 

// 因为$v等价于$data[2],相当于$data[2] = $data[1],把$data[2]赋值为b(即$data[1]); 此时数组array = ['a','b','b'];
$v = $data[1]; 

// 因为$v等价于$data[2],相当于$data[2] = $data[2],即赋值为其本身,而此时已经被上一次赋值为b; 此时数组array = ['a','b','b'];
$v = $data[2]; 

// 第二次遍历完后, array = ['a','b','b']

unset($v); // unset($v)释放掉临时的引用

var_dump($data);

最后输出:

array(3) {
  [0]=>
  string(1) "a"
  [1]=>
  string(1) "b"
  [2]=>
  string(1) "b"
}

首先要明白foreach是一个不断赋值的过程

第一轮循环实际是数组元素地址值的赋值,这并不会改变数组元素。看下面这个简单实例:

$t = array();
$t[0] = 3;
$t[1] = 4;
$a = &$t[0];
$a = &$t[1];
echo $t[0]; // 数组第一个元素并没有被改成4

开始第二轮循环之前,并没有销毁$v这个指针变量,它其实是指向数组最后一个元素的。
循环第一次,$v='a',实际是将数组最后一个元素更改成'a',这个时候打印数组就是'a','b','a'
循环第二次,$v='b',实际是将数组最后一个元素更改成'b',这个时候打印数组就是'a','b','b'
循环第二次,$v='b',实际是将数组最后一个元素更改成'b',这个时候打印数组就是'a','b','b'
所以这就是数组最后的值。

这个经典问题鸟哥早就说明过了,这里的一个点需要注意的是,第一次循环结束,$v是$data[2]的引用就可以了。
上面的答案讲的都很好了,我这里只能来一份补充资料,从php源码角度解析的php引用,给你网址吧:https://www.cnblogs.com/ohmyg...

这个问题好老啊,不过上面的大神解释的很详细。我对传引用的理解就是引用和赋值的变量共用了一块地址空间

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
1 篇内容引用
推荐问题