摘要:本文整理自網(wǎng)站上的一篇文章在循環(huán)中,如果使用引用會引發(fā)非常奇怪的行為這是的一個(gè)嗎問題在我寫一個(gè)簡單的腳本時(shí),發(fā)生了一些非常奇怪的現(xiàn)象。在中,如果一個(gè)內(nèi)存空間是被引用的,那么當(dāng)改變它的時(shí)候是直接改變這塊內(nèi)存空間的值。
本文整理自 stackoverflow 網(wǎng)站上的一篇文章 Strange behaviour after loop by reference - Is this a PHP bug? —— 在 PHP 循環(huán)中,如果使用 引用 會引發(fā)非常奇怪的行為 - 這是 PHP 的一個(gè) bug 嗎?
問題在我寫一個(gè)簡單的 PHP 腳本時(shí),發(fā)生了一些非常奇怪的現(xiàn)象。下面是我的代碼,為了清楚的表達(dá)我的意思,我特意去掉了一些不必要的代碼:
輸出如下:
Array ( [0] => foo [1] => bar [2] => baz ) Array ( [0] => foo [1] => bar [2] => bar // 錯(cuò)誤發(fā)生?? )這是 PHP 的一個(gè) bug 嗎?PHP 中為什么會發(fā)生如此古怪的行為呢?
解析在第一個(gè) foreach 循環(huán)結(jié)束后,$item 仍然引用(reference)著數(shù)組的最后一個(gè)元素,也就是 $arr[2]。 因此,當(dāng)開始第二個(gè)循環(huán)的時(shí)候,$item 變量每次循環(huán)都會被賦一個(gè)新值。 在 php 中,如果一個(gè)內(nèi)存空間是被引用的,那么當(dāng)改變它的時(shí)候是直接改變這塊內(nèi)存空間的值。 當(dāng)改變 $item 的時(shí)候,其實(shí)也改變了 $arr[2] 的值。
因此,在第二個(gè)循環(huán)中:
第一次循環(huán),$item 和 $arr[2] 的值變成 $arr[0],也就是 "foo"。
第二次循環(huán),$item 和 $arr[2] 的值變成 $arr[1],也就是 "bar"。
第三次循環(huán),$item 和 $arr[2] 的值變成 $arr[2],也就是 "bar"($arr[2] 的值不是 "baz",因?yàn)樵诘诙窝h(huán)中變成了 "bar")。
"baz" 的值實(shí)際是在第二個(gè)循環(huán)中丟失了。
譯注:我不喜歡把 reference 翻譯成「引用」,當(dāng)然了,更不能翻譯成「參考」了。每次我像別人解釋 reference 時(shí),都會告訴他: reference 就是 alias。 比如你叫吳毅昌(呵呵,無異常),二狗子是你的別名。本著好兄弟好基友的情誼:“來,二狗子,這 100 塊錢給你吧?!?你——吳毅昌——回家一??诖?,多了 100 塊錢。 @justjavac
調(diào)試輸出我們可以修改代碼來調(diào)試并跟蹤循環(huán)的執(zhí)行細(xì)節(jié)。 我們可以輸出 $item 的值,并且遞歸的輸出數(shù)組 $arr。
當(dāng)?shù)谝粋€(gè)循環(huán)運(yùn)行時(shí),我們可以看到這樣的輸出:
foo Array ( [0] => foo [1] => bar [2] => baz ) bar Array ( [0] => foo [1] => bar [2] => baz ) baz Array ( [0] => foo [1] => bar [2] => baz )在循環(huán)結(jié)束后,$item 和 $arr[2] 指向同一個(gè)內(nèi)存區(qū)域。
當(dāng)?shù)诙€(gè)循環(huán)運(yùn)行時(shí),我們看到這樣的輸出:
foo Array ( [0] => foo [1] => bar [2] => foo ) bar Array ( [0] => foo [1] => bar [2] => bar ) bar Array ( [0] => foo [1] => bar [2] => bar )在這次循環(huán)中,需要注意隨著每次 $item 被賦予一個(gè)新值, $arr[2] 也會被賦值為和 $item 相同的值,因?yàn)樗鼈兌既匀恢赶蛳嗤膬?nèi)存空間(譯注:原文寫的是 $arr[3],疑為原作者筆誤。@justjavac)。 當(dāng)循環(huán)到達(dá)數(shù)組的第三個(gè)值時(shí),它包含的值是 bar,因?yàn)樗闹翟谇皟纱窝h(huán)中,被修改了。
還有疑問也許你覺得,我僅僅是執(zhí)行了一個(gè)空循環(huán) foreach ($arr as &$item){},循環(huán)體里面什么都沒有做,為什么數(shù)組元素卻改變了?
可能你覺得這個(gè)代碼應(yīng)該等價(jià)于
for ($i = 0; $i < count($arr); $i++) { // do nothing }其實(shí)不對,代碼應(yīng)該等價(jià)于:
for ($i = 0; $i < count($arr); $i++) { $item = $arr[$i]; }也就是說, 在 foreach 循環(huán)中,隱含了一個(gè)賦值運(yùn)算,唯一不同的時(shí), 在賦值過程中,我們使用了引用,所以在第一個(gè)循環(huán)中,無意中修改了正在循環(huán)的數(shù)組內(nèi)部的元素。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/20609.html
摘要:在的官方手冊中寫道支持風(fēng)格的前后遞增與遞減運(yùn)算符。第一個(gè)注意事遞增遞減運(yùn)算符不影響布爾值。遞增遞減布爾值遞增遞減在處理字符變量的算數(shù)運(yùn)算時(shí),沿襲了的習(xí)慣,而非的。還有一個(gè)注意事項(xiàng)遞增遞減其他字符變量則無效,原字符串沒有變化。 在 PHP 的官方手冊中寫道: PHP 支持 C 風(fēng)格的前/后遞增與遞減運(yùn)算符。 第一個(gè)注意事:遞增/遞減運(yùn)算符不影響布爾值。遞減 NULL 值也沒有...
摘要:中基礎(chǔ)中的三大坑,遍歷,引用機(jī)制,數(shù)組。今天我們在講講中的一些奇怪現(xiàn)象。本文適合有一定基礎(chǔ)的。運(yùn)行流程共用一個(gè)結(jié)構(gòu)體開始遍歷數(shù)組,進(jìn)行判斷,拷貝數(shù)組是一個(gè)新的結(jié)構(gòu)體,操作的是新的結(jié)構(gòu)體。那么遍歷數(shù)組時(shí),全程與原數(shù)組無關(guān)。 PHP中基礎(chǔ)中的三大坑,foreach遍歷,引用機(jī)制&,數(shù)組。 今天我們在講講foreach中的一些奇怪現(xiàn)象。 在講解之前,可以先看看我其他相關(guān)的文章,屬于同一個(gè)大的...
摘要:總結(jié)垃圾回收機(jī)制以的引用計(jì)數(shù)機(jī)制為基礎(chǔ)以前只有該機(jī)制同時(shí)使用根緩沖區(qū)機(jī)制,當(dāng)發(fā)現(xiàn)有存在循環(huán)引用的時(shí),就會把其投入到根緩沖區(qū),當(dāng)根緩沖區(qū)達(dá)到配置文件中的指定數(shù)量后,就會進(jìn)行垃圾回收,以此解決循環(huán)引用導(dǎo)致的內(nèi)存泄漏問題開始引入該機(jī)制 php垃圾回收機(jī)制,對于PHPer來說是一個(gè)不陌生但是又不是很熟悉的內(nèi)容。那么php是怎么實(shí)現(xiàn)對不需要的內(nèi)存進(jìn)行回收的呢? php變量的內(nèi)部存儲結(jié)構(gòu) 首先還是...
摘要:背景項(xiàng)目中通過遠(yuǎn)程調(diào)用服務(wù)框架調(diào)用了許多其它的服務(wù)其中有一個(gè)服務(wù)需要升級其升級不是版本上的升級而是整個(gè)服務(wù)重新取了一個(gè)名字使用的也是全新的包但是調(diào)用的方法沒有改變因此在升級時(shí)只是在調(diào)用服務(wù)類中修改了調(diào)用地址和調(diào)用返回實(shí)體由改為該中返回該調(diào)用 背景 項(xiàng)目中通過遠(yuǎn)程調(diào)用服務(wù)框架調(diào)用了許多其它的服務(wù),其中有一個(gè)服務(wù)wx/subscribe/contract/CircleService 需要升...
摘要:這種行為比最初出現(xiàn)的問題更為棘手,同時(shí)也是一種常見的錯(cuò)誤源。這意味著這個(gè)數(shù)組的一份拷貝將會被返回,因此被調(diào)函數(shù)與調(diào)用者所訪問的數(shù)組并不是同樣的數(shù)組實(shí)例。 showImg(https://segmentfault.com/img/bV7reP?w=620&h=620); PHP 語言讓 WEB 端程序設(shè)計(jì)變得簡單,這也是它能流行起來的原因。但也是因?yàn)樗暮唵?,PHP 也慢慢發(fā)展成一個(gè)相對...
閱讀 2501·2021-11-17 09:33
閱讀 796·2021-11-04 16:13
閱讀 1358·2021-10-14 09:50
閱讀 718·2019-08-30 15:53
閱讀 3693·2019-08-30 14:18
閱讀 3287·2019-08-30 14:14
閱讀 2127·2019-08-30 12:46
閱讀 3208·2019-08-26 14:05