[PHP - 雷] foreach 與 reference 的雷
前言
前陣子公司定期技術研討會時,有人提出了一個問題。
$arr = [1, 2, 3];
foreach ($arr as &$a) {}
foreach ($arr as $a) {}
var_dump($arr);
考慮以上程式碼執行結果,試問陣列 $arr
在執行結束後的值會是如何?
註:執行環境 PHP 7.1 without swoole
結果:$arr
的值為 [1, 2, 2]
緣由
在 PHP 中,foreach
結束後,迴圈中的索引值(index)及內容(value)並不會被消滅。
$a = [1, 2, 3];
foreach ($a as $v) {}
var_dump($v); // int(3)
foreach ($a as $k => $value) {}
var_dump($k, $value); // int(2), int(3)
同理,foreach ($a as &$v) {}
時,在迴圈結束後 $v
值不會被消滅,其值仍是參考於(referenced by)陣列中的最後一個值,執行範例如下:
$a = [1, 2, 3];
foreach ($a as &$v) {}
var_dump($a);
/*
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
&int(3)
}
*/
如果在迴圈結束後變更 $v
值,則陣列中的最後一個值也會一併被變更。
解決方法
在使用 foreach ($a as &$v) {}
這類寫法後,應手動 unset($v)
以避免潛在問題發生。
$a = [1, 2, 3];
foreach ($a as &$v) {
// do something...
}
unset($v);
參考資料
http://php.net/manual/en/control-structure...
在 Warning
中有明確指出此問題。
本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由 Summer
于 7年前 加精
高认可度评论:
@Lichmaker 這個出成筆試題就有點不太厚道了。
我一直在強調,人腦不是、也不該是 compiler,不該用很刁鑽或炫技的考題來測試面試者。
以前触发过这个雷,现在写的时候,都是先写上unset
上星期去面试的时候遇到过一模一样的笔试题...
@Lichmaker 這個出成筆試題就有點不太厚道了。
我一直在強調,人腦不是、也不該是 compiler,不該用很刁鑽或炫技的考題來測試面試者。
只需要在foreach中的value 都不相同就可以完美的避过去了吧
@xhh110 +1 从来不会让 foreach 中的使用过的两个参数在其他地方使用
@xhh110 沒錯,只不過要注意在同個變數存在域下不可對同個變數進行賦值,與其檢查這個不如直接用完就隨手
unset
掉@JokerLinly 我也是这样的循环用一样的值在我公司里我分分钟想打死他
@ChiVincent 不检查 强制要求循环不能用一个名称就好了。。。哈哈哈
并不建议使用&,不懂它就最好不要乱用
这里补充下为什么结果为
[1, 2, 2]
第一次
foreach
循环时由于使用了引用,因此在循环结束时$a
的值便是$arr[2]
了,在第二次循环时,实际上就是循环给$arr[2]
赋值