7月
16
2007
分類:
最近更新:
2007-07-16
foreach 時使用 reference 的陷阱
前幾天在重構一段 PHP 程式碼時,不小心踩到 foreach
使用「參照(reference)」的陷阱。上網查了一下,似乎踩到的人還不少。我想了一下,把原因換成另一段程式碼形式說明,再說明解法。基本上,這是個 trick ,而不是 bug 。
一段很平常的迴圈敘述,差別僅在第一個迴圈使用參照(PHP5 or later),第二個不是。
<?php
$a = array(1,2,3);
foreach ($a as &$v) {
echo $v,"\n";
}
echo "----\n";
foreach ($a as $v) {
echo $v,"\n";
}
?>
預期輸出結果。
1 2 3 ---- 1 2 3
實際輸出結果。
1 2 3 ---- 1 2 2
因為 $v 在第一個迴圈時,被設定為一個參照。當迴圈結束後,$v 正好參照最後一個陣列元素 $a[2] 。而接下來的迴圈,就成為參照的指派動作,把每個一陣列元素的值都透過參照 $v 指派為最後一個陣列元素 $a[2] 了。每次輸出的結果實際上都是 $a[2] 的現值。第二個迴圈的動作等同下列所示:
<?php
$a = array(1,2,3);
foreach ($a as &$v) {
echo $v,"\n";
}
echo "----\n";
/*
$v is still reference to $a[2],
so this iterator will like following:
*/
reset($a);
while( $t = current($a) ) {
$v = $t; //$v ref $a[2], so $a[2] will be $t
echo $v,"\n";
next($a);
}
?>
解決這個問題的方式是,在使用參照的迴圈結果後,加上一個 unset
的動作消除那個參照變數。如下所示。
<?php
$a = array(1,2,3);
foreach ($a as &$v) {
echo $v,"\n";
}
unset($v);
?>
按 PHP 目前的特性,這是個好習慣。
樂多舊網址: http://blog.roodo.com/rocksaying/archives/3669955.html
樂多舊回應