对数组两次foreach的使用陷阱
对同一个数组两次foreach备注
这个问题是作小论坛的时候遇见的
若是单纯的对一个数组两次foreach是没什么问题的数组
输出:spa
若是在第一次foreach的时候,加了引用呢?3d
输出:指针
第二次的结果是 a b b,并非数组的值
也就是说这种状况下,foreach循环最后一次的值和数组倒数第二个的值是同样的blog
输出:ip
为何第二次结果是a b b呢?
foreach循环时,是经过移动数组内部指针来实现的
第一次foreach循环时,$v为引用变量
于是$v 与 $arr[2] 指向了同一个地址空间(共享变量值)
因此以后对$v的任何修改都会直接影响$arr
图解:内存
第二次foreach的第一次循环时,$v被赋值为$arr[0],也就是a
而在第一次foreach结束时,$v最终指向了$arr[2],他们指向同一个地址空间
因此第二次foreach的第一次循环时,$v的值成了a,$arr[2]也就变成了a
第二次foreach的第二次循环时,$v的值成了b,$arr[2]也就变成了b
因此,数组$arr的值就成了a b b
因此第三次循环时,$v的值就成了bit
上面说的明白,不过···
第二次foreach循环时,$v=$arr[0],按照以前说的,$v的指向不是指向了$arr[0]吗?
也就是说$v和$arr[0]指向同一内存地址,由于$arr和$v都没有发生值的变化
这里咱们须要先了解一个知识点:class
结果:
1
2
2变量
结果:
2
2
2
主要是这代码的运行结果:
我觉得上面的代码中$v和$b应该指向同一zval,而$a的值不会被改变,但事实并不是这样
是否是说一个变量的引用(&)没有消失,对这个变量从新赋值(非引用)其它变量的时候,其内存地址不会发生变化,也就是该变量的引用、指向内存地址的那条线不会改变,只是值变化
结果:
1
2
2
结果:
1
2
2
因此,结果才会这样
输出:
那如今又有这样一个疑虑,理论上在第二次foreach循环中,不会拷贝数组,这里$arr的值虽然发生了变化,但并非直接经过$arr[$k]这样的方式去改变的,而是$v的值被改变,$v是个临时变量,间接的影响到了$arr数组的值,因此数组不会拷贝
(目前没想到更有说服力的理由)
三种解决方案:① 第二次foreach循环,别用$v了② 第二次foreach循环以前,unset($v)$v的引用在 foreach 循环以后仍会保留。建议使用unset()将其销毁③ 第二次循环也用&