成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

PHP 循環(huán)中「引用」引發(fā)的奇怪問題

Riddler / 499人閱讀

摘要:本文整理自網(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

相關(guān)文章

  • PHP 「自增、自減」運(yùn)算引發(fā)奇怪問題

    摘要:在的官方手冊中寫道支持風(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 值也沒有...

    madthumb 評論0 收藏0
  • foreach遍歷過程奇怪現(xiàn)象(PHP5)

    摘要:中基礎(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è)大的...

    kgbook 評論0 收藏0
  • php底層原理之垃圾回收機(jī)制

    摘要:總結(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) 首先還是...

    light 評論0 收藏0
  • 增量部署class文件引發(fā)血案

    摘要:背景項(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 需要升...

    lolomaco 評論0 收藏0
  • 十個(gè) PHP 開發(fā)者最容易犯錯(cuò)誤

    摘要:這種行為比最初出現(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è)相對...

    fireflow 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<