1 背景
我們經常在PHP中使用for和foreach來進行遍歷操作,那它們除了語法上的區別之外,還有什麼不同嗎?
2 實驗
2.1 for
<?php
$a = ['a', 'b', 'c'];
for ($i = 0; $i < count($a); $i++) {
$a[] = $a[$i];
}
var_dump($a);
輸出
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 134217736 bytes) in /box/script.php on line 5
Exited with error status 255
內存爆了。
原因是在for循環裏面,一直在往$a中追加元素,而每次元素的新增都會增加$a的長度,導致$i < count($a) 這個條件一直成立,於是這個for循環變成了一個死循環,無法退出,最後內存爆掉。
可以看出,在for循環中,PHP會在每一次迭代中,忠實地去檢查for循環的條件、邊界,然後判斷是否執行for循環體裏面的內容。這個結論可以延伸到while循環以及do-while循環。
2.2 foreach
<?php
$a = ['a', 'b', 'c'];
foreach ($a as $k => $v) {
$a[] = $a[$k];
}
var_dump($a);
輸出
array(6) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
[2]=>
string(1) "c"
[3]=>
string(1) "a"
[4]=>
string(1) "b"
[5]=>
string(1) "c"
}
可以看到,在foreach循環中,PHP會事先確定好要遍歷數組的迭代次數,然後依次迭代。它的底層原理是,foreach是對數組的副本進行操作,而且每一次迭代,都是通過元素之間的指針來實現,比如current, next, rewind, valid, end等方法;當迭代器判斷當前指針指向空節點的時候,valid返回false,就表示迭代完成了,底層是一個鏈表。