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

資訊專欄INFORMATION COLUMN

foreach遍歷過程中的奇怪現(xiàn)象(PHP5)

kgbook / 2086人閱讀

摘要:中基礎(chǔ)中的三大坑,遍歷,引用機(jī)制,數(shù)組。今天我們?cè)谥v講中的一些奇怪現(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ù)組。

今天我們?cè)谥v講foreach中的一些奇怪現(xiàn)象。

在講解之前,可以先看看我其他相關(guān)的文章,屬于同一個(gè)大的知識(shí)點(diǎn),都看看有助于理解。

當(dāng)我們使用foreach時(shí),內(nèi)部究竟發(fā)生了什么?(PHP5)

PHP底層分析:關(guān)于寫時(shí)復(fù)制(cow)

PHP底層分析:關(guān)于強(qiáng)制分裂

△△△寫前聲明:以下結(jié)論都基于PHP5版本,因?yàn)闀r(shí)代在進(jìn)步,在PHP7中內(nèi)部的結(jié)構(gòu)體模塊和引用模塊均發(fā)生重大變化,PHP7的foreach輸出規(guī)則也旋即發(fā)生變化。當(dāng)然,由于PHP7想要普及還需要一到兩年(今年是2016)時(shí)間,所以這篇文章還是有些價(jià)值的,至少可以讓你先理解一下PHP內(nèi)部實(shí)現(xiàn)。

有疑問可以直接在評(píng)論中拋出,我會(huì)一一解答。

本文適合有一定基礎(chǔ)的PHPer。

那么開始上圖,這是鳥哥(惠新宸,PHP7核心開發(fā)組成員,開發(fā)組中唯一的一個(gè)中國(guó)人[撒花])在Think 2015 PHP技術(shù)峰會(huì)上的一個(gè)演講截圖,他在講述PHP5的foreach和PHP7的foreach區(qū)別,我們把他演講中提及到PHP5的部分拿出來看看。

那么我們著重看下這幅圖的三段代碼執(zhí)行流程。

我講講三段代碼的運(yùn)行原理

code1.php

 $value) {
    var_dump(current($a));     //output int(2) int(2) int(2)
}
?>

輸出值為: int(2) int(2) int(2)。

同學(xué)們可能納悶了,乍一看并沒有發(fā)生明顯的寫時(shí)復(fù)制(相關(guān)文章)或者強(qiáng)制分裂(相關(guān)文章),怎么會(huì)是三個(gè)"2"呢。

關(guān)鍵點(diǎn)在于current()函數(shù)上:

foreach循環(huán)開始,拷貝一個(gè)數(shù)組出來,然后refcount_gc=2(foreach原理不太了解的同學(xué),可以看看我的另一篇文章:當(dāng)我們使用foreach時(shí),內(nèi)部究竟發(fā)生了什么?(PHP5) )

此時(shí)原數(shù)組($a)和拷貝數(shù)組(我這里命名為$a_copy)的指針均指向下標(biāo)1,

隨后進(jìn)入大括號(hào)執(zhí)行體,current()操作的參數(shù)必須是引用數(shù)組(紅線部分),如果不是引用數(shù)組的話會(huì)強(qiáng)制轉(zhuǎn)換成引用數(shù)組(即結(jié)構(gòu)體中is_ref__gc從0 -> 1)。

根據(jù)強(qiáng)制分裂原理,一個(gè)結(jié)構(gòu)體的is_ref__gc的值從0 -> 1的時(shí)候,如果refcount_gc=2時(shí),就會(huì)發(fā)生url"強(qiáng)制分裂了"。

強(qiáng)制分裂后, 原數(shù)組($a)和拷貝數(shù)組(我這里命名為$a_copy)結(jié)構(gòu)體已經(jīng)不一樣,但是foreach操作的是拷貝數(shù)組($a_copy),原數(shù)組被丟在半道上了,所以三次輸出var_dump(current($a))均為2

code2.php


這段代碼和code1.php原理差不多,只是在foreach前進(jìn)行了一次引用賦值,結(jié)構(gòu)體變化成:refcount_gc=2;is_ref_gc=1; 隨后foreach遍歷數(shù)組,此時(shí)原數(shù)組($a),拷貝數(shù)組(我這里命名為$a_copy)和$b的指針均指向下標(biāo)1并且均為引用數(shù)負(fù)責(zé)(is_ref_gc)。

接著進(jìn)入大括號(hào)執(zhí)行體:var_dump(current($a)); 前面說道",current()操作的參數(shù)必須是引用數(shù)組(紅線部分),如果不是引用數(shù)組的話會(huì)強(qiáng)制轉(zhuǎn)換成引用數(shù)組(即結(jié)構(gòu)體中is_ref__gc從0 -> 1)。"

此處參數(shù)$a已經(jīng)為引用數(shù)組,不會(huì)發(fā)生強(qiáng)制分裂,原數(shù)組($a)和拷貝數(shù)組($a_copy)為同一個(gè)結(jié)構(gòu)體,正常輸入為:int(2) int(3) bool(false)

code3.php

 $value) {
    var_dump(current($a));    //output int(1) int(1) int(1)
}
?>

第三段代碼和前面兩個(gè)又有所不同了,這次$b=$a是使用傳值賦值,那么此處為什么為3個(gè)int(1)呢?這次的原因在于foreach的機(jī)制:

foreach循環(huán)之前,需要判斷數(shù)組的 refcount計(jì)數(shù),如果大于1,拷貝數(shù)組自己成為一個(gè)新的結(jié)構(gòu)體,循環(huán)過程操作的是新的結(jié)構(gòu)體。

運(yùn)行流程:
line:3; // $a,$b共用一個(gè)結(jié)構(gòu)體

line:4; //foreach開始遍歷數(shù)組,進(jìn)行refcount判斷,拷貝數(shù)組是一個(gè)新的結(jié)構(gòu)體,foreach操作的是新的結(jié)構(gòu)體。那么遍歷數(shù)組時(shí),全程與原數(shù)組無關(guān)。

Line:5: //打印數(shù)組當(dāng)前單元,由于原數(shù)組和拷貝數(shù)組已不是一個(gè)結(jié)構(gòu)體,所以原數(shù)組的指針沒變過,打印出int(1)。

如果還是有些不明覺厲的話,可以反復(fù)看多幾遍,對(duì)了,再次推薦看下這幾篇文章,都能理解的話對(duì)foreach掌握也差不多夠用了。

當(dāng)我們使用foreach時(shí),內(nèi)部究竟發(fā)生了什么?(PHP5)

PHP底層分析:關(guān)于寫時(shí)復(fù)制(cow)

PHP底層分析:關(guān)于強(qiáng)制分裂

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/30347.html

相關(guān)文章

  • 當(dāng)我們使用foreach時(shí),內(nèi)部究竟發(fā)生了什么(PHP5)?

    摘要:如何證明我的說法呢可以用下面這段代碼檢驗(yàn)。那么在這里我們需要特別注意,為了保險(xiǎn)起見我們?cè)诒闅v數(shù)組后,最好手動(dòng)一下數(shù)組,防止出錯(cuò)這樣就正常了。還有一點(diǎn)手冊(cè)也提醒我們了轉(zhuǎn)成代碼的意思就是遍歷后和是真實(shí)存在的,最好使用后能手動(dòng)掉。 以下所有結(jié)論均基于PHP5版本看下面一段最基礎(chǔ)的foreach遍歷數(shù)組代碼。 輸出為’0a1b2c’自然沒有疑問,那么此過程中$arr,$key,$valu...

    paulli3 評(píng)論0 收藏0
  • php中Generator的執(zhí)行過程

    摘要:說到中的生成器,有人可能會(huì)想到協(xié)程,這里我們先不說如何實(shí)現(xiàn)協(xié)程,我們探究下的執(zhí)行過程。如果函數(shù)包含了關(guān)鍵字的,那么函數(shù)執(zhí)行后的返回值永遠(yuǎn)都是一個(gè)對(duì)象。如果函數(shù)內(nèi)部同事包含和該函數(shù)的返回值依然是對(duì)象,但是在生成對(duì)象時(shí),語句后的代碼被忽略。 說到php中的Generator(生成器),有人可能會(huì)想到協(xié)程,這里我們先不說php如何實(shí)現(xiàn)協(xié)程,我們探究下Generator的執(zhí)行過程。 Gene...

    Caicloud 評(píng)論0 收藏0
  • 深入理解PHP之foreach

    摘要:建議使用來將其銷毀。那為何一直是,一直是呢先用查看編譯后的新特性之循環(huán)對(duì)數(shù)組內(nèi)部指針不再起作用在之前當(dāng)數(shù)據(jù)通過迭代時(shí)數(shù)組指針會(huì)移動(dòng)。版本結(jié)果說明數(shù)組指針會(huì)移動(dòng)數(shù)據(jù)指針不再移動(dòng)按照值進(jìn)行循環(huán)時(shí)對(duì)數(shù)組的修改是不會(huì)影響循環(huán)。 招聘 標(biāo)簽(空格分隔): 招聘 PHP 國(guó)貿(mào) 語言基礎(chǔ) foreach 語法結(jié)構(gòu)提供了遍歷數(shù)組的簡(jiǎn)單方式。 php5之前, foreach僅能用于數(shù)組php5+, 利...

    Lemon_95 評(píng)論0 收藏0
  • JS 數(shù)組循環(huán)遍歷方法的對(duì)比

    摘要:循環(huán)方法方法不改變?cè)瓟?shù)組方法會(huì)給原數(shù)組中的每個(gè)元素都按順序調(diào)用一次函數(shù)。篩選出過濾出數(shù)組中符合條件的項(xiàng)組成新數(shù)組代碼方法方法為數(shù)組中的每個(gè)元素執(zhí)行一次函數(shù),直到它找到一個(gè)使返回表示可轉(zhuǎn)換為布爾值的值的元素。 showImg(https://segmentfault.com/img/bV2QTD?w=1600&h=500); 前言 JavaScript 發(fā)展至今已經(jīng)發(fā)展出多種數(shù)組的循環(huán)遍...

    BlackFlagBin 評(píng)論0 收藏0
  • For與while時(shí)間的對(duì)比

    摘要:結(jié)果分析雖然我沒有代碼,但是我猜測(cè)是循環(huán)執(zhí)行語句的多少差別。如果有更好的原因可以評(píng)論或者發(fā)起后話生命不息,技術(shù)不止。很多時(shí)候我也為了代碼量的減少不理會(huì)運(yùn)行時(shí)間的差異,這次吸收教訓(xùn),之后在實(shí)際開發(fā)會(huì)更加注意時(shí)間。 ????本文首發(fā)于cartoon的博客????轉(zhuǎn)載請(qǐng)注明出處:https://cartoonyu.github.io/cartoon-blog/post/java/for%E4...

    lcodecorex 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

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