2012-09-07 45 views
12

我有一個疑問在PHP foreach迭代。Php foreach-爲什麼它在迭代時不覆蓋數組值?

請看下面我的代碼。

CODE:

$arr=array(1,2,3); 

    echo '$arr value : '. $arr; 

    echo '<br>'; 

    foreach($arr as $arr){ 
     echo $arr.'<br>'; 
    } 
    echo '$arr value : '. $arr; 

OUTPUT:

$arr value : Array 
1 
2 
3 
$arr value : 3 

雖然遍歷數組我用同樣的數組名值鍵foreach($arr as $arr)但它工作正常。它是如何工作的?

爲什麼它不重寫迭代時的數組值?

我想知道foreach迭代是如何工作的。

請幫幫我!

預先感謝 洛根

+2

這絕對是一個令人驚訝的輸出。 –

+0

does not php以某種方式緩存原始$ arr(數組)的內容,然後在循環時,它會更改並顯示$ arr(如1,2和3),然後最後$ arr保留爲「3」 ,因爲它只是不會保存緩存的值,回到原來的文件,因爲PHP不希望你重寫它。 –

+0

它令人驚訝。 –

回答

13

爲什麼不能覆蓋迭代時的數組值?

foreach將在原始數組的副本上工作,因此您在foreach循環中更改的內容不會更改正在循環的值。

+1

埃米爾與簡單的Rep收益。幹得好;)hehe +1! –

-2

foreach第一迭代它的元素之前評估的左側。因此,重新分配名稱$ arr不會修改$ arr。

此外,循環變量泄漏到外背景下,作爲documented

一個$value的參考和最後一個數組元素甚至foreach循環後仍然存在。建議通過unset()銷燬它。

當然,爲了避免混亂,你只需要使用不同的名稱爲循環變量比數組你遍歷:

$arr=array(1,2,3); 
foreach($arr as $a) { // Note the "as $a", not "as $arr" 
    echo $a.'<br>'; 
} 
echo '$arr value : '. $arr; 
+5

我認爲這是個問題 - 爲什麼當變量具有相同的名稱時它的工作方式如此。 –

+0

@MarekKarbarz修正了答案。 – phihag

0

$ arr和$ arr在您的代碼中是一樣的。源數組和參考變量具有相同的名稱。所以foreach保留上次接收到的值,但不放棄變量。

-1

嗯,以後有點調查我來到了這個代碼:

<?php 
$arr=array(1,2,3); 

echo '$arr value : '. $arr; 

echo '<br>'; 

foreach($arr as $arr){ 
    echo $arr.'<br>'; 
} 

foreach($arr as $key) { 
    echo $key.'<br>'; 
} 
echo '$arr value : '. $arr; 

其中有這樣的輸出:

$arr value : Array 
1 
2 
3 
PHP Warning: Invalid argument supplied for foreach() in ...file... 

我對這個讀是第二$arr被遮蔽第一一個在foreach循環內,但一旦它退出foreach循環,它會在內部取消設置符號($arr

+2

它不會取消它,它會用'foreach'的最後一個值覆蓋它。所以你第二個'foreach'試圖循環一個單一的值,而不是一個數組 –

+0

甚至沒有想到,這更糟糕。 –

0

foreach使用原始數組的副本,讓你能想到的代碼

foreach($arr as $arr){ 
    echo $arr.'<br>'; 
} 

就像如下:

for ($i = 0, $arr_tmp = $arr, $len = count($arr_tmp); $i < $len; $i++) { 
    $arr = $arr_tmp[$i]; 
    echo $arr.'<br>'; 
} 

這就解釋了爲什麼$arr3最後。

3

PHP使用copy on writelazy copy機制與reference counting進行內存處理。

在foreach迭代的第一階段,$arr是「軟拷貝」(沒有實際的拷貝,但只有zvalzval增加了)。 PHP變量結賬variable container and label

在我們的情況下,

  • 它首先保持一個參考實際$arr變量,數組的第一個值是從參考點取。
  • 供以後使用第一個數組元素被分配給第二$arr的foreach($改編爲$的常用3
  • 在下一迭代中,第二陣列值爲預先保存的參考點取,並且該值被分配給相同的$arr並繼續。
  • 由於$arr的值在循環內部發生更改,因此無法使用$arr變量在循環外部打印該數組。

希望您能理解......

對於深入研究結賬http://www.php.net/manual/en/internals2.opcodes.fe-fetch.phphttp://www.php.net/manual/en/internals2.opcodes.fe-reset.php

有趣的是,你可以用這個也玩...

current() foreach循環內將始終返回相同的元素!

代碼

$source = array(10, 20, 30); 
foreach ($source as $value) { 
    echo 'Value is ', $value, ', and current() is ', current($source), '<br>'; 
} 

輸出

Value is 10, and current() is 20 
Value is 20, and current() is 20 
Value is 30, and current() is 20 
0

你在寫作時你取一個記錄數組,你問的代碼來從$ ARR的紀錄,並把它放入名爲$ arr的數組中,因此您正在使用單個參數 寫入整個數組,前 $ arr = {1,2,3}; 這條線和第一次迭代 的foreach後($改編爲$ ARR)現在的$ ARR等於3,數組的最後一個元素,我希望你下架問題

1
foreach ($arr as $arr) { 
    // code 
} 

這可能是令人困惑,因爲你的是如何工作的心智模式是:

  1. PHP取當前元素出來$arr和墊款數組指針
  2. 它將值以$arr
  3. 它執行// code
  4. 它從步驟重複一個

什麼雖然它實際上是這個(或至少近似的它簡化):

  1. PHP開始foreach操作,取這與$arr
  2. 它把這個陣列內部的某個地方相關數組值,比方說,一個var iterator
  3. 它取從var iterator S中的當前元素和前進迭代
  4. 它分配它採取$arr在腳本中的值
  5. 它執行// code
  6. 它從步驟3

重複換言之,它在每次迭代時都不會從$arr中獲取下一個值,它只會使用這一次來獲取初始迭代器。它迭代的實際內容存儲在內部,不再與$arr關聯。這意味着$arr對於腳本中的其他用途是免費的,PHP很樂意在每次迭代時重用它。循環完成後,最後一個元素保留在$arr中。

如果你知道匿名函數,這也許說明了更好的,爲什麼這個作品它的工作方式:

foreach($arr, function ($arr) { 
    // code 
}); 

這種foreach功能的實現可以簡單:

function foreach(array $array, callable $code) { 
    while (list(, $value) = each($array)) { 
     $code($value); 
    } 
} 
+0

+1,除了最後一個說明性示例沒有解釋爲什麼'$ arr'在循環後更改:-) –

+0

是的,在匿名函數中,$ arr不會泄漏到周圍的範圍。這實際上是我認爲最簡單的事情,因爲「循環變量在循環之後仍然可用並且具有最後一個值」,不管變量名稱如何,它都可以工作... :) – deceze

相關問題