php中foreach循環中鍵值使用&的問題

WBOY
發布: 2016-08-04 09:19:49
原創
1308 人瀏覽過

程式碼如下:

<code>$a = [1, 2, 3];
foreach($a as $key => &$value) {
    $value = 5;
}
var_dump($a);</code>
登入後複製
登入後複製

最後輸出結果如下:

<code>array(3) { [0]=> int(5) [1]=> int(5) [2]=> &int(5) }</code>
登入後複製
登入後複製

問題:為什麼會在最後的鍵值前出現取位址符號?

回覆內容:

程式碼如下:

<code>$a = [1, 2, 3];
foreach($a as $key => &$value) {
    $value = 5;
}
var_dump($a);</code>
登入後複製
登入後複製

最後輸出結果如下:

<code>array(3) { [0]=> int(5) [1]=> int(5) [2]=> &int(5) }</code>
登入後複製
登入後複製

問題:為什麼會在最後的鍵值前出現取位址符號?

這個var_dump裡出現的&代表你可以用一個其他的變數來改變它的值。
比如你這樣

<code class="php">$b = &$a[0];
var_dump($a);</code>
登入後複製

這裡印出來的時候就會在第一個鍵值裡出現&符號,表示你可以用其他變數($b)來改變它的值。

先來了解&的基本用法。

<code class="php">$b = $c = 1;
$a = &$b;
$a = 2;
echo "b=$b,c=$c\n";
$a = &$c;
$a = 100;
$a = 200;
echo "b=$b,c=$c\n";
unset($a);
$a = 500;
echo "b=$b,c=$c\n";</code>
登入後複製

上面$a指定成$b的引用之後,除非再次指定成其他引用,或unset($a),否則改變$a就是改變對應的$b的值。

對於你這個foreach,也是同樣的道理,你把循環單步拆開,就是這個樣子:

<code class="php">$value = &$a[0];
$value = 5;
$value = &$a[1];
$value = 5;
$value = &$a[2];
$value = 5;</code>
登入後複製

循環運行到最後的時候,$value是$a[2]的引用,所以就等於這麼個形式:

<code class="php">$a[0] = 5;
$a[1] = 5;
$value = &$a[2];
$a[2] = 5;
var_dump($a);</code>
登入後複製

也就不難理解為什麼var_dump會在最後的鍵值對上印出一個&的符號了吧。


一般情況下這個不會導致什麼大問題,只不過由於foreach的作用域問題,會導致在循環退出之後$value依舊可以使用,所以會出現一些匪夷所思的bug。

比如這樣

<code class="php">$a = [1, 2, 3];
foreach($a as $key => &$value) {
    $value = $value+5;
}
var_dump($a); // [6,7,8]
foreach($a as $value){}
var_dump($a); // [6,7,7]</code>
登入後複製

加了一句空的foreach之後,反而導致$a變的不合理了,這個bug匪夷所思,原因也是因為那個空foreach裡的$value是最上面那個&a[2]的引用。

那個空foreach相當於這樣:

<code class="php">$value = &$a[2];
$value = $a[0];
$value = $a[1];
$value = $a[2];</code>
登入後複製

注意到了麼,由於$value是$a[2]的引用,所以上面的改寫一下就是這樣:

<code class="php">$a[2] = $a[0];
$a[2] = $a[1];
$a[2] = $a[2];</code>
登入後複製

空foreach裡在不停的改變$a[2],而由於$a[2]已經變成$a[1]的值了,所以$a[2] = $a[2];沒有任何影響,值還是$a[1];

這種匪夷所思的bug是由於$value這個變數的作用域導致的,所以要嘛改個名,要嘛先把$value給unset掉。

<code class="php">$a = [1, 2, 3];
foreach($a as $key => &$value) {
    $value = $value+5;
}
var_dump($a);
// 要么unset
unset($value);
// 要么foreach里不要用上面同名的$value,改为$value2222
foreach($a as $value2222){}
var_dump($a);</code>
登入後複製

首先我想說,這是一個非常非常好的問題。我相信題主並不是分不清引用與非引用。
我先做了兩個測試:

<code>$a = [1, 2, 3];
foreach($a as $key => &$value) {
    $value = 5;
}
foreach($a as $key => $value) {
    $value = 6;
}
var_dump($a);</code>
登入後複製

你猜輸出是什麼?

<code>array(3) {
  [0]=>  int(5)
  [1]=>  int(5)
  [2]=>  &int(6)
}</code>
登入後複製

另外一個檢定是:

<code>$a = [1, 2, 3];
foreach($a as $key => &$value) {
    $value = 5;
}
foreach($a as $key => $value2) {
    $value2 = 6;
}
var_dump($a);</code>
登入後複製

這次的輸出就看起來正常多了:

<code>array(3) {
  [0]=>  int(5)
  [1]=>  int(5)
  [2]=>  &int(5)
}</code>
登入後複製

所以說,這個問題應該是php全域變數的一個坑。

相關標籤:
php
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板