国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

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

kgbook / 2061人閱讀

摘要:中基礎中的三大坑,遍歷,引用機制,數組。今天我們在講講中的一些奇怪現象。本文適合有一定基礎的。運行流程共用一個結構體開始遍歷數組,進行判斷,拷貝數組是一個新的結構體,操作的是新的結構體。那么遍歷數組時,全程與原數組無關。

PHP中基礎中的三大坑,foreach遍歷,引用機制&,數組。

今天我們在講講foreach中的一些奇怪現象。

在講解之前,可以先看看我其他相關的文章,屬于同一個大的知識點,都看看有助于理解。

當我們使用foreach時,內部究竟發生了什么?(PHP5)

PHP底層分析:關于寫時復制(cow)

PHP底層分析:關于強制分裂

△△△寫前聲明:以下結論都基于PHP5版本,因為時代在進步,在PHP7中內部的結構體模塊和引用模塊均發生重大變化,PHP7的foreach輸出規則也旋即發生變化。當然,由于PHP7想要普及還需要一到兩年(今年是2016)時間,所以這篇文章還是有些價值的,至少可以讓你先理解一下PHP內部實現。

有疑問可以直接在評論中拋出,我會一一解答。

本文適合有一定基礎的PHPer。

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

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

我講講三段代碼的運行原理

code1.php

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

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

同學們可能納悶了,乍一看并沒有發生明顯的寫時復制(相關文章)或者強制分裂(相關文章),怎么會是三個"2"呢。

關鍵點在于current()函數上:

foreach循環開始,拷貝一個數組出來,然后refcount_gc=2(foreach原理不太了解的同學,可以看看我的另一篇文章:當我們使用foreach時,內部究竟發生了什么?(PHP5) )

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

隨后進入大括號執行體,current()操作的參數必須是引用數組(紅線部分),如果不是引用數組的話會強制轉換成引用數組(即結構體中is_ref__gc從0 -> 1)。

根據強制分裂原理,一個結構體的is_ref__gc的值從0 -> 1的時候,如果refcount_gc=2時,就會發生url"強制分裂了"。

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

code2.php


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

接著進入大括號執行體:var_dump(current($a)); 前面說道",current()操作的參數必須是引用數組(紅線部分),如果不是引用數組的話會強制轉換成引用數組(即結構體中is_ref__gc從0 -> 1)。"

此處參數$a已經為引用數組,不會發生強制分裂,原數組($a)和拷貝數組($a_copy)為同一個結構體,正常輸入為:int(2) int(3) bool(false)

code3.php

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

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

foreach循環之前,需要判斷數組的 refcount計數,如果大于1,拷貝數組自己成為一個新的結構體,循環過程操作的是新的結構體。

運行流程:
line:3; // $a,$b共用一個結構體

line:4; //foreach開始遍歷數組,進行refcount判斷,拷貝數組是一個新的結構體,foreach操作的是新的結構體。那么遍歷數組時,全程與原數組無關。

Line:5: //打印數組當前單元,由于原數組和拷貝數組已不是一個結構體,所以原數組的指針沒變過,打印出int(1)。

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

當我們使用foreach時,內部究竟發生了什么?(PHP5)

PHP底層分析:關于寫時復制(cow)

PHP底層分析:關于強制分裂

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/30347.html

相關文章

  • 當我們使用foreach時,內部究竟發生了什么(PHP5)?

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

    paulli3 評論0 收藏0
  • php中Generator的執行過程

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

    Caicloud 評論0 收藏0
  • 深入理解PHP之foreach

    摘要:建議使用來將其銷毀。那為何一直是,一直是呢先用查看編譯后的新特性之循環對數組內部指針不再起作用在之前當數據通過迭代時數組指針會移動。版本結果說明數組指針會移動數據指針不再移動按照值進行循環時對數組的修改是不會影響循環。 招聘 標簽(空格分隔): 招聘 PHP 國貿 語言基礎 foreach 語法結構提供了遍歷數組的簡單方式。 php5之前, foreach僅能用于數組php5+, 利...

    Lemon_95 評論0 收藏0
  • JS 數組循環遍歷方法的對比

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

    BlackFlagBin 評論0 收藏0
  • For與while時間的對比

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

    lcodecorex 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<