当将存在的对象分配给数组时,我有一种奇怪的行为。在下面的示例中,我有一个包含一个属性的类。我用3个实例创建第一个数组(让我们称之为2-4-6),然后使用第一个数组的一个对象(实例4)创建第二个具有其他两个实例的数组。在修改第二个数组中对象的值以创建两个新实例(即实例3-5)时,实例4也被修改。因此,在第一个数组查询中,我得到了正确的值(2-4-6),但是在创建第二个数组之后,我得到了修改后的值(2-5-6)。我希望赋值操作符复制对象,但它反而创建了对实例的引用。在这个例子中,我可以通过显式调用克隆来解决这个问题,但是在更大的范围内,这不是工作(错误的代码优化?)。关于如何避免这个问题,有什么线索(或良好做法)吗?谢谢!
<?php
class TestBase
{
private int $m_test = 0;
public function SetTest(int $v)
{
$this->m_test = $v;
}
public function GetTest() : int
{
return $this->m_test;
}
}
function getNewList(TestBase $ref) : array
{
$newlist = [3 => new TestBase(), 5 => $ref];
$newlist[3]->SetTest(3);
$newlist[5]->SetTest(5);
return $newlist;
}
$listOfTest = [2 => new TestBase(), 4 => new TestBase(), 6 => new TestBase()];
$listOfTest[2]->SetTest(2);
$listOfTest[4]->SetTest(4);
$listOfTest[6]->SetTest(6);
foreach ($listOfTest as $test)
{
echo $test->GetTest().'<br>';
}
// 2
// 4
// 6
//$ref = clone $listOfTest[4];
$ref = $listOfTest[4];
$newList = getNewList($ref);
foreach ($listOfTest as $test)
{
echo $test->GetTest().'<br>';
}
// 2
// 5
// 6
?>发布于 2022-02-03 03:22:17
问题在于PHP使用数组的方式。只有当参数和lvalue都是对数组的引用时,才能通过引用分配数组。如果传入一个对象,它将被复制,并在两个地方设置对它的引用。随后对lvalue的重新分配不会对原始数组产生任何影响。
引用一个现有的数组,然后使用clone复制它,就可以解决这个问题。下面的示例展示了如何做到这一点,但您也可以使用工厂或其他方法创建一个新数组,该数组具有对所有现有元素的引用(方法是在每个元素上调用get_object_vars() )。
<?php
function getNewList(TestBase $ref) : array
{
$newlist = [3 => clone $ref, 5 => clone $ref];
$newlist[3]->SetTest(3);
$newlist[5]->SetTest(5);
return $newlist;
}
//$ref = clone $listOfTest[4];
$ref = &$listOfTest[4];
var_dump($ref); // TestBase Object (1) (2) { ["m_test"]=> int(5) }
//$newList = getNewList($ref);
foreach ($listOfTest as &$test)
{
echo "before: ".$test->GetTest().'<br>'; // 2, 4, 6 in output here!
var_dump($test); // TestBase Object (1) (2) { ["m_test"]=> int(4) }
echo "after: ".$test->GetTest().'<br>'; // 2, 4, 6 in output here!
var_dump($test); // TestBase Object (1) (2) { ["m_test"]=> int(4) }
}
?>https://stackoverflow.com/questions/70965532
复制相似问题