关于 PHP 引用的一个问题引发的思考

问题一

我们先来看一段代码:

$a=[1,2,3];   

foreach($a as &$v){

} 

foreach($a as $v){

}
var_dump($a);

我们来看一下运行结果是什么

array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  &int(2)
}

是不是和大家想的不一样。

我们注意到运行结果里面,数组的最后一个元素是带有引用,这就是出现这样结果的关键所在。

让我们来分析一下运行过程,当程序运行完第一个循环之后,由于循环的变量$v是引用类型,而在循环结束之后,变量 $v 会被保留下来,并且作为引用类型指向数组 $a 的最后一个元素。这样在执行第二个循环的时候,会将 $a[0]$a[1]的值依次赋值给 $v, 也即 $a[2]。所以在最后一次循环之前,$a[2] 的值变成了 2。而最后一次循环的时候,并不会改变 $a[2]的值,这样就得到了上面的结果。

总结
造成以上结果的主要原因是,如果循环使用的变量是引用类型的话,循环结束,这个变量会作为引用变量被保留下来,并且指向循环变量的最后一个元素。所以在循环外修改这个变量的话,会影响循环变量最后一个元素的值。
因此在写代码的时候,如果循环使用的变量是引用类型的话,在循环结束可以对变量进行 unset 操作,这样就不会有这样的问题了。

问题二

让我们再来看一段代码

$a=[1,2,3];
foreach($a as $v){
    $a[2] = 0;
    var_dump($a);
    var_dump($v);
}

让我们来看一下运行结果

array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(0)
}
int(1)
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(0)
}
int(2)
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(0)
}
int(3)

然我們稍微改一下代码

$b = &$a[2];
foreach($a as $v){
    $b = 0;
    var_dump($a);
    var_dump($v);
}

运行结果如下

array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  &int(0)
}
int(1)
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  &int(0)
}
int(2)
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  &int(0)
}
int(0)

看出来不同了么?

对于第一段代码 Demo,在数组循环开始之后,在循环中修改数组的值不会影响循环;而如果有引用变量指向数组的元素,在循环中修改引用变量的值则会影响循环。

你可能感兴趣的:(关于 PHP 引用的一个问题引发的思考)