PHP5对象是通过引用传递的吗?

时间:2010-04-26 16:17:18

标签: php

我似乎无法得到任何一致的信息。不同的来源似乎说不同的东西和古老的php.net本身(出现)不明确说明这一点 - 虽然,我必须承认,我只是快速看一下。

如果我在传递'重'对象,我需要通过引用传递,但我不想继续输入:

function foo(TypeName& $obj)

如果我能完全逃脱

function foo(TypeName $obj)

那么标准说的是什么?

8 个答案:

答案 0 :(得分:89)

通过引用传递(和分配)对象。无需使用运营商的地址。

当然,我输入的内容过于简单,但适合您的目的。 documentation州:

  

PHP5 OOP的关键点之一   经常提到的是“对象   默认情况下通过引用传递“。   这不完全正确。这个   部分纠正了一般的思想   使用一些例子。

     

PHP引用是别名,它是   允许两个不同的变量   写入相同的值。从PHP5开始,   对象变量不包含   将自己视为价值。它   仅包含对象标识符   它允许对象访问者查找   实际的对象。当一个物体是   通过参数发送,返回或分配   到另一个变量,不同   变量不是别名:它们持有一个   标识符的副本,指向哪个   同一个对象。

有关更详细的说明(解释过度简化和标识符),请查看this answer

答案 1 :(得分:8)

来自PHP manual

  

您可以通过引用传递变量   一个功能所以功能可以   修改变量。语法如下   如下:

<?php
function foo(&$var)
{
    $var++;
}

$a=5;
foo($a);
// $a is 6 here
?>
     

注意:a上没有参考标记   函数调用 - 仅在函数上   定义。功能定义   单独就足以正确传递   参考的论点。截至PHP   5.3.0,你会收到一条警告说“通过参考传递通话”是   使用&amp;时弃用在   FOO(安培; $ A);

来自What's New in PHP5

  

在PHP 5中,基础设施   对象模型被重写为工作   带有对象句柄。除非你   使用显式克隆对象   你永远不会克隆的关键字   在场景后面创建重复的   你的对象。在PHP 5中,有   既不需要传递对象   引用或分配它们   参考

因此,您需要使用function foo(&$var)语法的唯一时间是$ var可能不是类的实例。

答案 2 :(得分:5)

似乎更精确一点,对象的值是按值传递的,但对象本身的值是一个指针。这与传递引用不同。

http://www.php.net/manual/en/language.oop5.references.php上列出的示例很不错。在第一组中,$ a = NULL;不会影响$ b,因为$ a只是一个指针。在第二组中,$ c = NULL;导致$ d也为NULL,因为$ d是对$ c的引用。

<?php
class A {
    public $foo = 1;
}  

$a = new A;
$b = $a;
$a->foo = 2;
$a = NULL;
echo $b->foo."\n"; // 2

$c = new A;
$d = &$c;
$c->foo = 2;
$c = NULL;
echo $d->foo."\n"; // Notice:  Trying to get property of non-object...
?> 

答案 3 :(得分:3)

从PHP 5开始,所有对象都通过引用传递和分配。

在PHP 4中,您仍然需要通过显式使用&运算符来指定通过引用传递对象的位置。

答案 4 :(得分:2)

简短回答。来自Objects and references

  

PHP5 OOP的关键点之一   经常提到的是“对象   默认情况下通过引用传递“。   这不完全正确。这个   部分纠正了一般的思想   使用一些例子。

     

PHP引用是别名,它是   允许两个不同的变量   写入相同的值。从PHP5开始,   对象变量不包含   将自己视为价值。它   仅包含对象标识符   它允许对象访问者查找   实际的对象。当一个物体是   通过参数发送,返回或分配   到另一个变量,不同   变量不是别名:它们持有一个   标识符的副本,指向哪个   同一个对象。

重要的是,在您担心的情况下,除非您在函数调用中明确使用 clone 关键字,否则您永远不会复制对象。无论是别名还是标识符都不会改变这一事实。

答案 5 :(得分:2)

只是传递&#34;对象&#34;通过引用是有用的:

class RefTest1
{
    public $foo;

    public function __construct(RefTest2 &$ref = null)
    {
        $this->foo =& $ref;
    }
}

class RefTest2
{
    public $foo;

    public function __construct(RefTest1 &$ref = null)
    {
        $this->foo =& $ref;
    }
}

class RefTest3
{
    public $foo;

    public function __construct(RefTest2 &$ref = null)
    {
        $this->foo =& $ref;
    }
}

class DoCrossRef
{
    public $refTest1;
    public $refTest2;

    public function __construct()
    {
        $this->refTest1 = new RefTest1($this->refTest2);
        $this->refTest2 = new RefTest2($this->refTest1);
    }

    public function changeReference()
    {
        $this->refTest1 = new RefTest3($this->refTest2);
    }
}

最后RefTest1包含对RefTest2的引用,反之亦然,如果创建RefTest2RefTest1对象不存在。< / p>

调用DoCrossRef->changeReference()后,RefTest2个对象也会保留对新RefTest3对象的引用。

答案 6 :(得分:1)

从PHP5起,是的,对象通过引用传递。无需明确地做到这一点。

http://www.php.net/manual/en/migration5.oop.php

  

在PHP 5中有一个新的对象模型。 PHP对对象的处理已经完全重写,允许更好的性能和更多的功能。在以前的PHP版本中,对象的处理方式与原始类型(例如整数和字符串)相同。这种方法的缺点是语义上整个对象在分配变量时被复制,或者作为参数传递给方法。在新方法中,对象由句柄引用,而不是通过值引用(可以将句柄视为对象的标识符)。

答案 7 :(得分:0)

这是另一个确认对象通过引用传递的示例。

<?php

// discussion: https://stackoverflow.com/questions/2715026/are-php5-objects-passed-by-reference#_=_
class A {
    public $foo = 1;
}

class B {
    function inc($obj) {
        $obj->foo++;
    }
}

$objA = new A();
$objB = new B();
$objB->inc($objA);

echo "[" . $objA->foo . "]"; // Outputs [2]