對數組兩次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()將其銷燬③ 第二次循環也用&