php 引用遇到的问题

最近遇到这样的问题

$data = [1,2,3];
foreach ($data as &$v){}
foreach ($data as $v){}
print_r($data); //这里输出内容是什么 输出[1,2,2]

第一个foreach

首先理解&,它指向变量的内存地址,可以理解为C语言中的指针。ok ,先看看第一个foreach后,$data的内容
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  &int(3)
}
从上面可以看出$data[2]类型&int(3),变成了存储$data[2]的内存指针,由于foreach 结束之后$v并不会马上注销掉的,因此第一次foreach后$v也指向了data[2]的引用
$v = &$data[2]

也就说第一个foreach结束后,$v转变成了内存地址的引用不是简单的变量赋值了。

第二个foreach

foreach ($data as $v){}
//遍历第一个元素
$v = $data[0]; //此时$data[0]的值赋给 $v,而$v指向$data[2]的内存地址会导致$data[2] = $data[0],那么此时的$data为[1,2,1]
//遍历第二个元素
$v = data[1];//同理,此时$data变成了[1,2,2]
//遍历第三个元素
$v = data[2];//同理此时$data变成了[1,2,2]

嗯嗯,看以下代码

$a['a'] = 123;
$b = &$a['a']; //此时的$a['a']为引用类型了
$c = $a;//c['a'] = a['a']也为引用类型
$c['a'] = 456; 
print_r($a);//输出456

再看以下代码

$a['a'] = 123;
$b = &$a;
$c = $a;//纯粹的赋值
$c['a'] = 456;
print_r($a);//输出123

思考为什么第一段代码输出456,第二段代码输出123?
答:$b = &$a['a'];与$b = &$a;的区别,前者把数组a的元素变成的引用类型,后者是把a变量变成了引用类型, 所以当执行到$c = $a;赋值运算时,前者的$b会包含引用类型,而后者则是正常的赋值。

总结

在foreach 循环中慎用& ,容易出现意想不到的bug
修改引用类型变量的值,会改变该引用变量所指向的内容

参考资料

https://learnku.com/articles/7001/php-ray-foreach-and-references-thunder
https://www.laruence.com/2018/04/08/3179.html

你可能感兴趣的:(php 引用遇到的问题)