PHP 通过 foreach 中的引用传递

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3307409/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 09:17:39  来源:igfitidea点击:

PHP Pass by reference in foreach

php

提问by Centurion

I have this code:

我有这个代码:

$a = array ('zero','one','two', 'three');

foreach ($a as &$v) {

}

foreach ($a as $v) {
  echo $v.PHP_EOL;
}

Can somebody explain why the output is: zero one two two .

有人可以解释为什么输出是: zero one two two 。

From zend certification study guide.

来自 Zend 认证学习指南。

采纳答案by Macmade

Because on the second loop, $vis still a reference to the last array item, so it's overwritten each time.

因为在第二次循环中,$v仍然是对最后一个数组项的引用,所以每次都会被覆盖。

You can see it like that:

你可以这样看:

$a = array ('zero','one','two', 'three');

foreach ($a as &$v) {

}

foreach ($a as $v) {
  echo $v.'-'.$a[3].PHP_EOL;
}

As you can see, the last array item takes the current loop value: 'zero', 'one', 'two', and then it's just 'two'... : )

如您所见,最后一个数组项采用当前循环值:“零”、“一”、“二”,然后它只是“二”... :)

回答by M S

I had to spend a few hours to figure out why a[3] is changing on each iteration. This is the explanation at which I arrived.

我不得不花几个小时来弄清楚为什么 a[3] 在每次迭代中都会发生变化。这是我到达的解释。

There are two types of variables in PHP: normal variables and reference variables. If we assign a reference of a variable to another variable, the variable becomes a reference variable.

PHP 中有两种类型的变量:普通变量和引用变量。如果我们将一个变量的引用分配给另一个变量,该变量就成为一个引用变量。

for example in

例如在

$a = array('zero', 'one', 'two', 'three');

if we do

如果我们这样做

$v = &$a[0]

the 0th element ($a[0]) becomes a reference variable. $vpoints towards that variable; therefore, if we make any change to $v, it will be reflected in $a[0]and vice versa.

第 0 个元素 ( $a[0]) 成为参考变量。 $v指向那个变量;因此,如果我们对 进行任何更改$v,它将反映在$a[0],反之亦然。

now if we do

现在如果我们这样做

$v = &$a[1]

$a[1]will become a reference variable and $a[0]will become a normal variable (Since no one else is pointing to $a[0]it is converted to a normal variable. PHP is smart enough to make it a normal variable when no one else is pointing towards it)

$a[1]将成为一个引用变量$a[0]并将成为一个普通变量(因为没有其他人指向$a[0]它被转换为一个普通变量。当没有其他人指向它时,PHP 足够聪明,使它成为一个普通变量)

This is what happens in the first loop

这是第一个循环中发生的事情

foreach ($a as &$v) {

}

After the last iteration $a[3]is a reference variable.

最后一次迭代之后$a[3]是一个引用变量。

Since $vis pointing to $a[3]any change to $vresults in a change to $a[3]

因为$v是指向$a[3]任何更改$v导致更改为$a[3]

in the second loop,

在第二个循环中,

foreach ($a as $v) {
  echo $v.'-'.$a[3].PHP_EOL;
}

in each iteration as $vchanges, $a[3]changes. (because $vstill points to $a[3]). This is the reason why $a[3]changes on each iteration.

在每次迭代中随着$v变化,$a[3]变化。(因为$v仍然指向$a[3])。这就是为什么$a[3]每次迭代都会发生变化的原因。

In the iteration before the last iteration, $vis assigned the value 'two'. Since $vpoints to $a[3], $a[3]now gets the value 'two'. Keep this in mind.

在最后一次迭代之前的迭代中,$v被赋值为“二”。由于$v指向$a[3]$a[3]现在获得值“二”。记住这一点。

In the last iteration, $v(which points to $a[3]) now has the value of 'two', because $a[3]was set to two in the previous iteration. twois printed. This explains why 'two' is repeated when $v is printed in the last iteration.

在最后一次迭代中,$v(指向$a[3])现在的值为 'two',因为$a[3]在前一次迭代中设置为 2。two被打印。这解释了为什么在最后一次迭代中打印 $v 时会重复 'two'。

回答by TaeL

First loop

第一次循环

$v = $a[0];
$v = $a[1];
$v = $a[2];
$v = $a[3];

Yes! Current $v= $a[3]position.

是的!当前$v=$a[3]位置。

Second loop

第二个循环

$a[3] = $v = $a[0], echo $v; // same as $a[3] and $a[0] == 'zero'
$a[3] = $v = $a[1], echo $v; // same as $a[3] and $a[1] == 'one'
$a[3] = $v = $a[2], echo $v; // same as $a[3] and $a[2] == 'two'
$a[3] = $v = $a[3], echo $v; // same as $a[3] and $a[3] == 'two'

because $a[3]is assigned by before processing.

因为$a[3]是在处理之前分配的。

回答by shadyyx

I got here just by accident and the OP's question got my attention. Unfortunately I do not understand any of the explanations from the top. Seems to me like everybody knows it, gets it, accetps it, just cannot explain.

我偶然来到这里,OP 的问题引起了我的注意。不幸的是,我不明白上面的任何解释。在我看来,每个人都知道,得到,接受,只是无法解释。

Luckily, a pure sentence from PHP documentation on foreachmakes this completely clear:

幸运的是,从 PHP 文档中关于foreach 的一个纯句子完全清楚地说明了这一点:

Warning:Reference of a $valueand the last array element remain even after the foreach loop. It is recommended to destroy it by unset().

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

回答by Chang

I think this code show the procedure more clear.

我认为这段代码显示的程序更清晰。

<?php

$a = array ('zero','one','two', 'three');

foreach ($a as &$v) {
}

var_dump($a);

foreach ($a as $v) {
  var_dump($a);
}

Result: (Take attention on the last two array)

结果:(注意最后两个数组)

array(4) {
  [0]=>
  string(4) "zero"
  [1]=>
  string(3) "one"
  [2]=>
  string(3) "two"
  [3]=>
  &string(5) "three"
}
array(4) {
  [0]=>
  string(4) "zero"
  [1]=>
  string(3) "one"
  [2]=>
  string(3) "two"
  [3]=>
  &string(4) "zero"
}
array(4) {
  [0]=>
  string(4) "zero"
  [1]=>
  string(3) "one"
  [2]=>
  string(3) "two"
  [3]=>
  &string(3) "one"
}
array(4) {
  [0]=>
  string(4) "zero"
  [1]=>
  string(3) "one"
  [2]=>
  string(3) "two"
  [3]=>
  &string(3) "two"
}
array(4) {
  [0]=>
  string(4) "zero"
  [1]=>
  string(3) "one"
  [2]=>
  string(3) "two"
  [3]=>
  &string(3) "two"
}

回答by Goose

This question has a lot of explanations provided, but no clear examples of how to solve the problem that this behavior causes. In most cases, you'll probably want the following code in your pass by reference foreach.

这个问题提供了很多解释,但没有明确的例子说明如何解决这种行为导致的问题。在大多数情况下,您可能希望在 pass by reference 中使用以下代码foreach

foreach ($array as &$row) {
    // Do stuff
    // Unset
    unset($row);
}

回答by TTT

This :

这个 :

$a = array ('zero','one','two', 'three');

foreach ($a as &$v) {

}

foreach ($a as $v) {
    echo $v.PHP_EOL;
}

is the same as

是相同的

$a = array ('zero','one','two', 'three');

$v = &$a[3];

for ($i = 0; $i < 4; $i++) {
    $v = $a[$i];
    echo $v.PHP_EOL; 
}

OR

或者

$a = array ('zero','one','two', 'three');

for ($i = 0; $i < 4; $i++) {
    $a[3] = $a[$i];
    echo $a[3].PHP_EOL; 
}

OR

或者

$a = array ('zero','one','two', 'three');

$a[3] = $a[0];
echo $a[3].PHP_EOL;

$a[3] = $a[1]; 
echo $a[3].PHP_EOL;

$a[3] = $a[2];
echo $a[3].PHP_EOL;

$a[3] = $a[3]; 
echo $a[3].PHP_EOL;

回答by bpile

I found this example also tricky. Why that in the 2nd loop at the last iteration nothing happens ($v stays 'two'), is that $v points to $a[3] (and vice versa), so it cannot assign value to itself, so it keeps the previous assigned value :)

我发现这个例子也很棘手。为什么在最后一次迭代的第二个循环中什么也没有发生($v 保持“二”),是因为 $v 指向 $a[3](反之亦然),所以它不能为自己赋值,所以它保持先前分配的值:)

回答by Ahmed Aman

Because if you create a reference to a variable, all names for that variable (including the original) BECOME REFERENCES.

因为如果您创建对变量的引用,则该变量的所有名称(包括原始名称)都将成为引用。