看到一篇文章描(就是它)述了php的乙個語法特點,用文本來描述就是如果對乙個陣列進行foreach
引用遍歷過後在對這個陣列使用同樣的變數進行一次普通foreach
遍歷會導致這個陣列的值發生變化。
我這個描述可能還是不太清楚,直接上**:
可以看到在迴圈當中沒有任何**,所以兩次列印出來的資料肯定應該是一模一樣的,然而結果總是讓人意外:
我當時就驚呆了!還能這樣的?
文章中的解釋只有一句話:因為陣列最後乙個元素的 $value 引用在 foreach 迴圈之後仍會保留,在第二個迴圈的時候實際上是對之前的指標不斷的賦值。
看著這句話想了半天愣是沒想明白,然後又找到了php關於foreach
的文件:php 手冊=>語言參考=>流程控制
,我的內心深處告訴我不能就這樣算了,php的問題都搞不清楚還怎麼在php界立足,世界上最好的語言都搞不好怎麼去學習其他語言,想到這裡我的手又不由自主的開啟了搜尋引擎…
在我的一通搜尋中終於找到了一篇文章:php foreach使用 &引用 的坑:
很認真的看了幾遍,似乎有些眉目了,就是說在第一次foreach
迴圈結束以後裡面的變數$a
並沒有被銷毀,而是保留了下來,並且依舊是乙個引用2
變數。明白了這個並沒有解決我心中的疑慮:就算變數$a
沒有被銷毀,那麼在第二次的foreach
也要被覆蓋的,第一次迴圈$arr[2]
被覆蓋成了1
,第二次迴圈$arr[2]
被覆蓋成了2
,第三次迴圈$arr[2]
被覆蓋成了4
,迴圈結束$arr[2]
不還是4
嗎,咋列印出來就變成了2呢?
確實想不通,我在第二次迴圈中把$arr[2]
列印出來看一看,來驗證一次:
結果:
真是搞不懂第三次咋就變了,這個時候切記心浮氣躁,靜下心來捋一捋整個流程,從第一次迴圈結束開始:
前面說第一次迴圈結束後的的變數$a
是引用1
,怎麼證明呢?那多簡單,把變數$a
的型別列印出來看下不就知道了,找了下有個gettype()
函式,我們來試試:
看樣子這不是我想要的結果…只有再去搜尋一番了。
果然讓我發現了乙個新的函式xdebug_debug_zval()
,這個函式需要裝xdebug
擴充套件,關於這個函式的介紹可以看一下php官網:引用計數基本知識
這個函式不僅會列印出來變數的型別和值,還會有兩個額外資訊:is_ref
和refcount
,is_ref
表示這個變數是否為引用變數,refcount
表示指向這個zval變數容器的變數(也稱符號即symbol)個數。我們只需要看is_ref
就可以了:
結果:
從結果中可以看到is_ref
為1
即true
表示變數$a
確實是引用變數,然後我們繼續分析foreach
迴圈過程中的資料變化:
把$arr[0]
的值1
賦值給$a
,這時$a
的引用即$arr[2]
的值為1
;
把$arr[1]
的值2
賦值給$a
,這時$a
的引用即$arr[2]
的值為2
;
把$arr[2]
的值(注意了,第二步$arr[2]
的值已經被覆蓋為2
)2
賦值給$a
,這時$a
的引用即$arr[2]
的值為2
;
此時$arr
的值就是[1, 2, 2]
了。
經過這麼一遍梳理總算是搞清楚怎麼回事了,其實就是在第二次迴圈中通過賦值給引用變數改變了被迴圈陣列的值,導致原陣列值的變化,現在也理解了官方文件中那句警告是什麼意思了。
**搬運工。 ↩︎↩︎
可以理解為指標型別。 ↩︎
foreach之引用 的使用
廢話不說,上 arrayname array 0 array 1 houzi 2 xiaogou 1 array 2 houzi 3 xiaogou var dump arrayname foreach arrayname as key value var dump arrayname exit 結...
php填坑記之curl無法上傳檔案
今天上傳檔案 測試環境上傳無誤 正式環境確接受不到檔案資訊 如下 通過輸出 astatus 發現問題如下 測試環境下上傳結果如下 primary port int 80 local ip string 12 x local port int 53530 正式環境如下 primary port int...
填坑系列之更新CocoaPods
cocoapods的具體使用方法網上有很多,這裡不再贅述。在使用pod install安裝第三方庫時,可能會出現以下錯誤 出現這個問題是由於在swift3以後,很多框架需要在cocoapods1.1.0版本以上才能正常使用,因此我們需要更新cocoapods。終端輸入 curl l get.rvm....