首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对象赋值是在PHP中创建引用

对象赋值是在PHP中创建引用
EN

Stack Overflow用户
提问于 2022-02-03 03:17:43
回答 1查看 65关注 0票数 -1

当将存在的对象分配给数组时,我有一种奇怪的行为。在下面的示例中,我有一个包含一个属性的类。我用3个实例创建第一个数组(让我们称之为2-4-6),然后使用第一个数组的一个对象(实例4)创建第二个具有其他两个实例的数组。在修改第二个数组中对象的值以创建两个新实例(即实例3-5)时,实例4也被修改。因此,在第一个数组查询中,我得到了正确的值(2-4-6),但是在创建第二个数组之后,我得到了修改后的值(2-5-6)。我希望赋值操作符复制对象,但它反而创建了对实例的引用。在这个例子中,我可以通过显式调用克隆来解决这个问题,但是在更大的范围内,这不是工作(错误的代码优化?)。关于如何避免这个问题,有什么线索(或良好做法)吗?谢谢!

代码语言:javascript
复制
<?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
?>
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-03 03:22:17

问题在于PHP使用数组的方式。只有当参数和lvalue都是对数组的引用时,才能通过引用分配数组。如果传入一个对象,它将被复制,并在两个地方设置对它的引用。随后对lvalue的重新分配不会对原始数组产生任何影响。

引用一个现有的数组,然后使用clone复制它,就可以解决这个问题。下面的示例展示了如何做到这一点,但您也可以使用工厂或其他方法创建一个新数组,该数组具有对所有现有元素的引用(方法是在每个元素上调用get_object_vars() )。

代码语言:javascript
复制
<?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) }
    }
?>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70965532

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档