gpt4 book ai didi

PHP 类 : referenced variable in one method affects non-referenced variable in other method

转载 作者:行者123 更新时间:2023-12-04 15:00:09 27 4
gpt4 key购买 nike

我对以下示例中的行为感到困惑。我在一个项目中偶然发现了这个问题,我花了几个小时将问题缩小到一个简单的例子。所以这是我的简单测试类:

<?php
class Foo {
public $sess = [['name' => 'John']];

public function info() {
$this->runTest();
echo $this->sess[0]['name'];
}

private function runTest() {
$localSess = &$this->sess[0];
$this->sessTest();
}

private function sessTest() {
$sessCopy = $this->sess;
$this->sess[0]['name'] = 'Bob';
$this->sess = $sessCopy;
}
}

$myFoo = new Foo;
$myFoo->info();

意外的结果输出是:

Bob

如果 $localSess 只是一个简单的赋值而不是引用,输出是(如预期的):John

我不明白这是怎么回事。由于类属性 $sess 是一个数组而不是对象,因此对 $sessCopy 的赋值应该是一个简单的副本。但是,如果您在修改 $this->sess 后立即打印 $sessCopy 的内容,它将包含“name”的更改值。所以看起来好像 $sessCopy 毕竟是一个引用?但前提是调用方法中的 $localSess 是引用。为什么这很重要?顺便说一句,如果 $localSess 是对类属性的整个数组的引用,而不仅仅是它的第一个索引,那么一切都会按预期工作。

有人可以解释一下吗?如果一个函数中仅存在一个变量引用就可以影响另一个函数中局部变量(不是引用!)的内容,那么这似乎是危险和可怕的。

最佳答案

所以我决定创建一个更简单的示例来说明相同的问题:

$a = [['name' => 'John']];
$b = $a; // makes a copy of `$a`
$b[0]['name'] = "Bob";
echo $a[0]['name]; // returns "John" as expected

但是如果你这样做了:

$a = [['name' => 'John']];
/* var_dump($a) returns:
array(1) {
[0]=>
array(1) {
["name"]=>
string(4) "John"
}
}
*/
$local = &$a[0]; // seems to modify $a[0], so its type &array
/* var_dump($a) returns:
array(1) {
[0]=>
&array(1) {
["name"]=>
string(4) "John"
}
}
*/
$b = $a; // makes a copy of `$a`
$b[0]['name'] = "Bob";
echo $a[0]['name]; // returns "Bob"

我承认这种行为很奇怪,但在多个 PHP 文档注释中都有记录:

事实证明,这实际上是 2000 年首次报告的 PHP 错误:

本应更新文档,但我找不到:

Due to peculiarities of the internal workings of PHP, if a reference is made to a single element of an array and then thearray is copied, whether by assignment or when passed by value in afunction call, the reference is copied as part of the array. Thismeans that changes to any such elements in either array will beduplicated in the other array (and in the other references), evenif the arrays have different scopes (e.g. one is an argumentinside a function and the other is global)! Elements that did not havereferences at the time of the copy, as well as references assigned tothose other elements after the copy of the array, will behavenormally (i.e. independent of the other array).

但是,它已被标记为 Wont fixed,可能是出于性能原因。值得注意的评论:

We have discussed this issue and it will put a considerable slowdown on php's performance, to fix this properly.

Therefore this behaviour will be documented.

即使它从未被记录。

我已决定就此问题提出另一个错误报告,以查看在这个问题上的立场是否发生了变化。

我现在重新报告了这个问题: https://bugs.php.net/bug.php?id=80955

解决方案

一种解决方法是:

$b = unserialize(serialize($a));

另一个是:

function array_clone($array) {
return array_map(function($element) {
if ((is_array($element))) {
return array_clone($element);
} else if (is_object($element)) {
return clone $element;
} else {
return $element;
}
}, $array);
}

$b = array_clone($a);

关于PHP 类 : referenced variable in one method affects non-referenced variable in other method,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67106717/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com