PHP 通过引用错误?
PHP pass by reference bug?
不要通过引用传递。我知道.......但是.
谁能解释一下这是怎么回事?我会尝试解释我的想法,也许这是一个 PHP 错误。
下面的代码脚本显示了一个字符串数组通过引用传递的示例(我知道不是...),并且如果等于标志则更改字符串。
数组完整地从 foreach
循环中出来。字符串已按需要更改。所有其他值仍在数组中。
我将更改后的数组 不是通过引用 传递到另一个 foreach 循环中,并尝试使用与在第一个循环中使用。我假设变量名称将被重置为新值(类似于 $variable = "new value")。但是,似乎变量名没有被取消引用。
不知何故,在该循环中,原始数组被更改并出现重复的倒数第二个值,并且缺少原始的最后一个值。对于其他具有更长更复杂数组的情况,情况总是如此。
代码如下,有人可以验证。
1) 这是一个 PHP 错误,在第二个 foreach
循环中使用时变量没有取消引用吗?
2) 如果有人可以提供有关 PHP 幕后可能发生的引用变量的信息,我将很乐意理解。换句话说,为什么 foreach 会导致数组出现重复和缺失元素?
<?php
$array = ["one", "two", "three"];
$other_array = [];
echo "<pre>";
print_r($array);
echo "</pre>";
foreach($array as &$reference){
if($reference == "one") $reference = "one_changed";
}
echo "<pre>";
print_r($array);
echo "</pre>";
foreach($array as $reference){
array_push($other_array, $reference);
}
echo "====changed them but did not push onto array====<br>";
echo "====changed also====";
echo "<pre>";
print_r($array);
echo "</pre>";
echo "====changed also====";
echo "<pre>";
print_r($other_array);
echo "</pre>";
不是错误,如果你想重用以前用作参考的变量,你需要这样做:
unset($var);
具体来说,在您的第一个循环之后添加这一行:
foreach($array as &$reference){
if($reference == "one") $reference = "one_changed";
}
unset($reference); // <--- this
解决所有问题:
Array
(
[0] => one
[1] => two
[2] => three
)
Array
(
[0] => one_changed
[1] => two
[2] => three
)
====changed them but did not push onto array====<br>====changed also====Array
(
[0] => one_changed
[1] => two
[2] => three
)
====changed also====Array
(
[0] => one_changed
[1] => two
[2] => three
)
还有一件事。数组元素也可以是引用,例如:
$a = 1;
$c=[];
$c[0] =& $a;
$c[1] =& $a;
print_r($c);
$a=2;
print_r($c);
那将输出:
Array
(
[0] => 1
[1] => 1
)
Array
(
[0] => 2
[1] => 2
)
所以,为了解释您的代码中到底发生了什么……我宁愿通过。你创建一个引用的循环变量,然后你将它用作另一个循环中的 non-referenced 变量,并将它作为一个值推送到另一个数组中......搞砸了,我放弃了。
这不是"pass by reference",因为这里没有经过。
在 &
中修改 foreach
循环中的数组元素在 PHP manual page on foreach 中有所描述,并带有关于之后需要取消设置变量的警告。
Warning
Reference of a $value and the last array element remain even after the
foreach loop. It is recommended to destroy it by unset(). Otherwise
you will experience the following behavior:
不要通过引用传递。我知道.......但是.
谁能解释一下这是怎么回事?我会尝试解释我的想法,也许这是一个 PHP 错误。
下面的代码脚本显示了一个字符串数组通过引用传递的示例(我知道不是...),并且如果等于标志则更改字符串。
数组完整地从 foreach
循环中出来。字符串已按需要更改。所有其他值仍在数组中。
我将更改后的数组 不是通过引用 传递到另一个 foreach 循环中,并尝试使用与在第一个循环中使用。我假设变量名称将被重置为新值(类似于 $variable = "new value")。但是,似乎变量名没有被取消引用。
不知何故,在该循环中,原始数组被更改并出现重复的倒数第二个值,并且缺少原始的最后一个值。对于其他具有更长更复杂数组的情况,情况总是如此。
代码如下,有人可以验证。
1) 这是一个 PHP 错误,在第二个 foreach
循环中使用时变量没有取消引用吗?
2) 如果有人可以提供有关 PHP 幕后可能发生的引用变量的信息,我将很乐意理解。换句话说,为什么 foreach 会导致数组出现重复和缺失元素?
<?php
$array = ["one", "two", "three"];
$other_array = [];
echo "<pre>";
print_r($array);
echo "</pre>";
foreach($array as &$reference){
if($reference == "one") $reference = "one_changed";
}
echo "<pre>";
print_r($array);
echo "</pre>";
foreach($array as $reference){
array_push($other_array, $reference);
}
echo "====changed them but did not push onto array====<br>";
echo "====changed also====";
echo "<pre>";
print_r($array);
echo "</pre>";
echo "====changed also====";
echo "<pre>";
print_r($other_array);
echo "</pre>";
不是错误,如果你想重用以前用作参考的变量,你需要这样做:
unset($var);
具体来说,在您的第一个循环之后添加这一行:
foreach($array as &$reference){
if($reference == "one") $reference = "one_changed";
}
unset($reference); // <--- this
解决所有问题:
Array
(
[0] => one
[1] => two
[2] => three
)
Array
(
[0] => one_changed
[1] => two
[2] => three
)
====changed them but did not push onto array====<br>====changed also====Array
(
[0] => one_changed
[1] => two
[2] => three
)
====changed also====Array
(
[0] => one_changed
[1] => two
[2] => three
)
还有一件事。数组元素也可以是引用,例如:
$a = 1;
$c=[];
$c[0] =& $a;
$c[1] =& $a;
print_r($c);
$a=2;
print_r($c);
那将输出:
Array
(
[0] => 1
[1] => 1
)
Array
(
[0] => 2
[1] => 2
)
所以,为了解释您的代码中到底发生了什么……我宁愿通过。你创建一个引用的循环变量,然后你将它用作另一个循环中的 non-referenced 变量,并将它作为一个值推送到另一个数组中......搞砸了,我放弃了。
这不是"pass by reference",因为这里没有经过。
在 &
中修改 foreach
循环中的数组元素在 PHP manual page on foreach 中有所描述,并带有关于之后需要取消设置变量的警告。
Warning
Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset(). Otherwise you will experience the following behavior: