今天一個同事,寫了一段類似下面的代碼:
$a = array(1, 2, 3);foreach($a as $k => &$v){ $a[] = $v;}
預設的 128M 記憶體直接被撐爆了, 原因很簡單:每迴圈一次,都將 $a 數組增加一個 k-v,導致陷入一個無限迴圈中, 記憶體自然不夠用了。
關鍵不是這裡, 關鍵是將 $k => &$v 改為 $k => $v 後, 這個迴圈又可以正常執行了。
查閱 PHP 手冊中, 有一句:"Note:除非數組是被引用,foreach 所操作的是指定數組的一個拷貝,而不是該數組本身。"
是否因為第二種寫法 的 foreach 操作的是數組 $a 的拷貝,而第一種寫法操作的是 $a 的引用或者其本身?
否則這個邏輯錯誤應該是兩種寫法都會體現出來才對。
回複內容:
今天一個同事,寫了一段類似下面的代碼:
$a = array(1, 2, 3);foreach($a as $k => &$v){ $a[] = $v;}
預設的 128M 記憶體直接被撐爆了, 原因很簡單:每迴圈一次,都將 $a 數組增加一個 k-v,導致陷入一個無限迴圈中, 記憶體自然不夠用了。
關鍵不是這裡, 關鍵是將 $k => &$v 改為 $k => $v 後, 這個迴圈又可以正常執行了。
查閱 PHP 手冊中, 有一句:"Note:除非數組是被引用,foreach 所操作的是指定數組的一個拷貝,而不是該數組本身。"
是否因為第二種寫法 的 foreach 操作的是數組 $a 的拷貝,而第一種寫法操作的是 $a 的引用或者其本身?
否則這個邏輯錯誤應該是兩種寫法都會體現出來才對。
解答
首先,肯定你的回答,原因也跟你說的一樣,php裡引用傳遞和值傳遞的區別。至於調試,我建議使用Xdebug調試一下即可,列印數組的zval結構體,代碼如下:
&$value) { $arr[] = $value; xdebug_debug_zval('arr'); echo "\n";}
可以看到zval的結構體的成員:arr: (refcount=3, isref=1),isref欄位為1說明是arr的引用
新疑問
我本該安心的複習演算法,準備各種校招筆試的,但是無奈測試一下一個元素的數組,代碼:
&$value) { $arr[] = $value; xdebug_debug_zval('arr'); echo "\n";}
這個並沒有像我想得一樣進入死迴圈,考慮是否是foreach的內部實現機製造成的,求解釋!!