【问题标题】:Unexpected behavior with references引用的意外行为
【发布时间】:2014-06-03 17:49:59
【问题描述】:

我对引用有一些意外行为:

foreach ($this->data as &$row)
{
        $row['h'] = 1;
}

foreach ($this->data as $id => $row)
{
     ... in some cases $row[$id] = $row;
}

结果是数组的最后一个元素被数组的倒数第二个元素替换。使用以下代码修复它:

foreach ($this->data as $key => $row)
{
     $this->data[$key]['h'] = 1;
}

很遗憾,我没有更多时间花在这上面了。也许这是 PHP (PHP 5.5.9-1ubuntu4) 的错误或我不知道的参考?

【问题讨论】:

标签: php foreach reference


【解决方案1】:

有一个完全合乎逻辑的解释,这不是错误!

PHP 5 引入了直接修改数组内容的可能性,方法是通过引用而不是通过值将每个元素的值分配给迭代变量。考虑以下代码,例如:

$a = array (’zero’,’one’,’two’);

foreach ($a as &$v) {
}
foreach ($a as $v) {
}

print_r ($a);

很自然地认为,由于这个小脚本对数组没有任何作用,它不会影响其内容......但事实并非如此!事实上,该脚本提供了以下输出:

Array
(
[0] => zero
[1] => one
[2] => one
)

如您所见,数组已更改,最后一个键现在包含值“一”。这怎么可能?正如我们所期望的那样,第一个foreach 循环不会对数组进行任何更改。但是,它确实会导致为$v 分配对$a 的每个元素的引用,因此,当循环结束时,$v 实际上是对$a[2] 的引用。

当第二个循环开始时,$v 现在被分配了每个元素的值。但是,$v 已经是对$a[2] 的引用;因此,分配给它的任何值都将自动复制到数组的最后一个元素中!因此,在第一次迭代期间,$a[2] 将变为 0,然后变为 1,然后再次变为 1,被有效地复制到自身。要解决此问题,您应该始终取消设置您在按引用 foreach 循环中使用的变量,或者更好的是,完全避免使用前者。

【讨论】:

    【解决方案2】:

    当通过引用循环数组时,您需要在 for 循环结束时手动放开引用,以避免像这样的奇怪行为。所以你的第一个foreach 应该是:

    foreach ($this->data as &$row)
    {
        .... code ....
    }
    unset($row);
    

    在这种情况下, unset 只是破坏引用,而不是 $row 引用的内容。

    查看PHP foreach documentation中的警告

    【讨论】:

      猜你喜欢
      • 2011-03-16
      • 1970-01-01
      • 1970-01-01
      • 2010-12-03
      • 2020-09-18
      • 1970-01-01
      • 2015-10-28
      • 2016-12-02
      • 1970-01-01
      相关资源
      最近更新 更多