當 foreach 開始執行時,數組內部的指針會自動指向第一個單元。若是移動指針的結果超出了數組單元的末端,則退出循環。php
$array = [ 'name' => 'Jobs', 'age' => 50, ]; foreach ($array as $key => $value) { $value = 22; //賦值,可是沒有影響到$array[$key]位置的值,除非加上 $array[$key] = $value; }
上面的foreach 對數組內的值沒影響。有時候咱們爲了在循環過程當中改變數組項的值,在foreach的時候變量入口能夠加個&符號,表示,循環過程當中使用數組中原來的值,而不是一個複製的值,如數組
$array = [ 'name' => 'Jobs', 'age' => 50, ]; foreach ($array as $key => &$value) { //直接改變數組$array[$key]位置的值 $value = 22; }
結果輸出對比:函數
Array ( [name] => Jobs [age] => 50 ) Array ( [name] => 22 [age] => 22 )
$key
和$value
都是臨時變量,foreach的時候,把每一個數組單元的鍵分別賦值給$key
,把每一個數組單元的值分別賦給$value
,相等於$value=$arr[$key]
,$value=2
僅僅是改變了$value
的值(非&傳遞),並不會影響到$array[$key]
,天然也就不會影響到$array
。debug
而用第二種方法(引用)的時候,相等於$value=&$array[$key]
,$array[$key]
和$value
指向同一內存地址,$value=2
天然就改變了$array[$key]
的值,也就改變了$array
的值指針
循環時,
$key
和$value
都是臨時變量,只是賦值方式不一樣code
陷阱:兩次循環使用一樣的臨時變量的狀況下,若是第一次循環使用的是引用,那麼在第二次循環中即便沒有加&符號,臨時變量也是引用。這個引用指向了數組中最後一個元素(循環到了最後一個元素結束)。
內存
如:string
array = [ 'name' => 'php', 'age' => 123, ]; //標記爲循環1: foreach ($array as $key => &$value) { echo "key=$key, value=$value" . PHP_EOL; } //循環完後,最後一個元素 $value = &$array['age'], 這裏$value 和 $array['age'] 是引用關係,都是指向的同一個空間。 var_dump($array); 輸出結果以下: array(2) { ["name"]=> string(3) "php" ["age"]=> &int(123) } //標記爲循環2: foreach ($array as $key => $value) { //第一次循環進來 $value=$array['name'],此時$value = 'php',因爲咱們開始的引用中, $value 和 $array['age'] 創建了引用,因此這裏改變了$value的值, 其實就改變了 $array['name']的值,因此 $array['name'] = 'php', //之後的每次循環處理都和上面第一次相同 //獲得的結果:其實每次循環賦值給$value的值,都是給「標記爲循環1」中的最後一個元素在賦值,也就是說數組中最後一個元素的值 = 數組中的倒數第2個元素的值 echo "key=$key, value=$value" . PHP_EOL; }
上面的 foreach循環中輸出結果以下:變量
key=name, value=php key=age, value=123 key=name, value=php key=age, value=php
總結:兩次循環使用一樣的臨時變量的狀況下,若是第一次循環使用的是引用,那麼在第二次循環中即便沒有加&符號,臨時變量也是引用。
這個引用指向了數組中最後一個元素(循環到了最後一個元素結束)。
,獲得的最後數據結果就是數組中最後一個元素的值 = 數組中的倒數第2個元素的值 (也就是說,最後2個元素的值相同,且爲到倒數第2個元素的處理值)。擴展
方法1:在第二次循環以前,unset($value)
方法2:第二次foreach的時候使用不一樣名字的臨時變量
另:查看一個變量是不是引用可使用xdebug_debug_zval函數(須要有xdebug擴展)。
xdebug_debug_zval的結果形如: value: (refcount=2, is_ref=1)=123