PHP:当将两个元素数组作为 by value 参数传递时,为什么数组的一个元素是按引用的,而另一个元素是按值的?

PHP how come one element of the array is by reference and the other by value when passing a two element array as a by value parameter?

提问人:Roemer 提问时间:6/23/2022 更新时间:6/23/2022 访问量:54

问:

有人可以解释我在 PHP 8.1.6 中目睹的这种奇怪行为吗?

我想这种行为是符合标准的,我只是不明白。函数调用有一个按值划分的参数,但数组在调用后发生了变化,这都是因为对第一个元素的引用。

$arr = [3, 4];
$ref = &$arr[0] ;             // this statement causes the weird behaviour. Without it all is ok

print_r($arr);                // as expected
print_r(doSomethingTo($arr)); // as expected
print_r($arr);                // WHAT JUST HAPPENED?

function doSomethingTo($arr) {
    // $arr BY VALUE
    foreach($arr as $k => $v)
        $arr[$k]=$v+1 ;
    return $arr ;
}

结果:

Array
(
    [0] => 3
    [1] => 4
)
Array
(
    [0] => 4
    [1] => 5
)
Array
(
    [0] => 4
    [1] => 4
)

为什么?为什么对第一个数组元素的引用会改变 by 值参数传递的行为?第一个元素现在通过引用函数传递,第二个元素通过值传递! ???

谢谢你的解释!

php 参数 传递-引用 传递-值

评论

0赞 Barmar 6/23/2022
有一些与引用相关的奇怪错误,这看起来像是其中之一。
1赞 Barmar 6/23/2022
我在 7.4.1 和 5.6 中复制了它。
1赞 Sammitch 6/23/2022
使用 instead of ,您可以看到在操作的两端创建引用的位置。3v4l.org/DXWNd我的一般建议是不要使用引用,除非你对什么是引用和是什么(特别是不是指针)有坚如磐石的理解,并且你必须使用引用的不可避免的理由,因为它们很少像你期望的那样工作。var_dump()print_r()
0赞 Sammitch 6/23/2022
@Barmar如果这是一个错误,它自 PHP4 以来就一直存在。
0赞 Barmar 6/23/2022
@Sammitch 所以这可能是设计使然。

答:

1赞 Roemer 6/23/2022 #1

我在 https://www.php.net/manual/en/language.references.whatdo.php 上找到了一个有点复杂的公式答案

我将翻译这种特殊情况的答案。

许多人可能没有意识到的是,这并不意味着现在$a对$b的引用,而是$a和$b都成为对最初包含在$b中的相同的引用。$a =& $b

因此,在计算 $arr[0] 元素时,$ref成为对 3 值的引用。$ref = &$arr[0] ;

现在,当数组作为参数按值传递时,该数组始终是重复的。这里也发生了同样的情况。

这意味着 $arr[0] 引用也是重复的,即在重复数组中,会创建另一个对相同 3 值的引用。因此,我们有$ref,函数中的原始 $arr[0] $arr[0] 都是对 3 值的引用。

当这三个引用中的任何一个获得赋值时,值当然会发生变化。

谢谢你@Sammitch让我走上了正确的轨道!!

评论

0赞 Roemer 6/26/2022
对我来说,很难意识到的是,一个普通的变量或数组值不是对一个值的单一引用,因为文件名是指向文件的单个链接。对于文件,您可以有一个或多个指向同一文件的链接,所有链接只是同一文件的不同文件名。添加新链接不会更改文件或对其执行的操作的行为。变量和数组元素则不然。一旦引用,那里的行为就会改变。它实际上变成了一个完全不同的野兽。这是最大的教训,