12

我对 php foreach 迭代有疑问。

请看我下面的代码。

代码 :

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

    echo '$arr value : '. $arr;

    echo '<br>';

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

输出 :

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

在迭代数组时,我使用相同的数组名称来赋值键foreach($arr as $arr),但它工作正常。它是如何工作的?

为什么它在迭代时不覆盖数组值?

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

请帮我!

提前感谢洛根

4

8 回答 8

14

为什么它在迭代时不覆盖数组值?

foreach将在原始数组的副本上工作,因此您在 foreach 循环中更改的内容不会更改您正在循环的值。

于 2012-09-07T06:50:29.930 回答
3

PHP 使用带有引用计数copy on write的orlazy copy机制进行内存处理。

在foreach迭代的第一阶段,$arr是“软拷贝”(没有实际拷贝,只是增加了refcountof的zval$array。结帐variable containerlabelPHP 变量。

在我们的案例中,

  • 它首先保持对实际$arr变量的引用,然后从引用点获取数组的第一个值。
  • 供以后使用,第一个数组元素分配给第二个$arrforeach($arr as $arr )
  • 在下一次迭代中,从先前保存的参考点获取第二个数组值,并将该值分配给相同的值$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
于 2012-09-07T07:30:01.767 回答
1
foreach ($arr as $arr) {
    // code
}

这可能会让您感到困惑,因为您对其工作原理的心理模型是:

  1. PHP 取出当前元素$arr并推进数组指针
  2. 它将值分配给$arr
  3. 它执行// code
  4. 它从第一步开始重复

它实际上做了什么(或者至少是它的近似简化):

  1. PHP 开始foreach操作,取与关联的数组值$arr
  2. 它把这个数组放在内部的某个地方,比方说var iterator
  3. 它从当前元素中获取var iterator并推进迭代器
  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);
    }
}
于 2012-09-07T07:53:29.857 回答
0

$arr 和 $arr 在您的代码中是相同的。源数组和引用变量具有相同的名称。因此 foreach 保留最后收到的值,它不会放弃变量。

于 2012-09-07T06:51:08.873 回答
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

于 2012-09-07T07:00:21.290 回答
0

当您获取记录时,您正在编写数组,您要求代码从 $arr 获取记录并将其放入名为 $arr 的数组中,因此您在 $arr = {1 之前使用单个参数覆盖了整个数组,2,3}; 在这一行和第一次迭代 foreach ($arr as $arr) 之后,现在 $arr 等于 3 数组的最后一个元素,我希望你能理解这个问题

于 2012-09-07T07:50:49.143 回答
-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)

于 2012-09-07T06:52:59.493 回答
-2

foreach首先在迭代其元素之前评估左侧。因此,对名称 $arr 的重新分配不会修改 $arr。

此外,循环变量泄漏到外部上下文中,如记录

$value即使在 foreach 循环之后,对 a 和最后一个数组元素的引用仍然存在。建议通过 unset() 将其销毁。

当然,为了避免混淆,你应该简单地为循环变量使用一个不同的名称,而不是你正在循环的数组:

$arr=array(1,2,3);
foreach($arr as $a) { // Note the "as $a", not "as $arr"
    echo $a.'<br>';
}
echo '$arr value : '. $arr;
于 2012-09-07T06:49:35.453 回答