2012-09-07 49 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

相关问题