For循环通过引用复制对象,即使文档说他们按值复制对象?

时间:2014-12-28 01:59:53

标签: php for-loop reference

在迭代对象数组时,我对for循环的行为有点困惑。

PHP documentation

foreach (array_expression as $key => $value)
  

为了能够直接修改循环中的数组元素,在$ value之前加上&amp ;.在这种情况下,该值将通过引用分配。

基于此,我的印象是$value是数组中对象的副本(按值)。但是,要验证我刚刚运行此测试:

class test {
    public $foo = 1;
    function __construct($foo) {
        $this->foo = $foo;
    }
}

$testArray = array();
$testArray[] = new test(1);
$testArray[] = new test(2);
$testArray[] = new test(3);;

echo '$testArray' . '<pre>' . PHP_EOL;
print_r($testArray);
echo PHP_EOL . '</pre>';

foreach ($testArray as $test) {
    if ($test->foo == 2) {
        $temp = $test;
    }
}

$temp->foo = 'copied by value or reference?';

echo '$testArray' . '<pre>' . PHP_EOL;
print_r($testArray);
echo PHP_EOL . '</pre>';

令人惊讶的是,输出是:

$testArray
Array
(
    [0] => test Object
        (
            [foo] => 1
        )

    [1] => test Object
        (
            [foo] => 2
        )

    [2] => test Object
        (
            [foo] => 3
        )

)

$testArray
Array
(
    [0] => test Object
        (
            [foo] => 1
        )

    [1] => test Object
        (
            [foo] => copied by value or reference?
        )

    [2] => test Object
        (
            [foo] => 3
        )

)

我的困惑是,当我执行$temp = $test赋值时,它通过引用数组中的原始对象来复制,但我认为$test已根据文档按值复制了?< / p>


好的,也许我只是没有注意细则:

  

为了能够直接修改中的数组元素在$ value之前用&amp ;.在这种情况下,该值将通过引用分配。

所以让我们尝试一下我们修改循环内对象的测试:

class test {
    public $foo = 1;
    function __construct($foo) {
        $this->foo = $foo;
    }
}

$testArray = array();
$testArray[] = new test(1);
$testArray[] = new test(2);
$testArray[] = new test(3);;

echo '$testArray' . '<pre>' . PHP_EOL;
print_r($testArray);
echo PHP_EOL . '</pre>';

foreach ($testArray as $test) {
    if ($test->foo == 2) {
        $temp = $test;
        $temp->foo = 'copied by value or reference?';
    }
}

echo '$testArray' . '<pre>' . PHP_EOL;
print_r($testArray);
echo PHP_EOL . '</pre>';

输出:

$testArray
Array
(
    [0] => test Object
        (
            [foo] => 1
        )

    [1] => test Object
        (
            [foo] => 2
        )

    [2] => test Object
        (
            [foo] => 3
        )

)

$testArray
Array
(
    [0] => test Object
        (
            [foo] => 1
        )

    [1] => test Object
        (
            [foo] => copied by value or reference?
        )

    [2] => test Object
        (
            [foo] => 3
        )

)

结果是一样的。看来该对象是通过引用复制的,即使文档明确暗示它们是按值复制的。

是什么给出了?

1 个答案:

答案 0 :(得分:3)

  

从PHP 5开始,对象变量不包含对象本身   价值了。它只包含允许的对象标识符   对象访问器来查找实际对象。当一个对象被发送时   参数,返回或分配给另一个变量,不同   变量不是别名:它们包含标识符的副本,即   指向同一个对象。

http://php.net/manual/en/language.oop5.references.php

编辑:我第一次遇到相反的问题,我需要按值复制对象
就像$new_obj = clone $original_obj一样,如果你的对象很简单......如果你有一个包含其他对象的对象,最终会在数组或子数组中变成一场噩梦!在不同类中有几个__clone()魔术函数,对于一些棘手的案例有些令人头疼...... 我终于消灭了所有这些clone__clone()的东西并选择了以下解决方案:

$new_obj = unserialize(serialize($original_obj));  

这里有关这个解决方案的有趣的赞成/评论,在我的案例中是最好的 - 或者至少是最简单的:-): How do I create a copy of an object in PHP?