如果对象通过别名传递,您何时通过引用传递?

时间:2012-07-19 15:10:39

标签: php

  

可能重复:
  In PHP can someone explain cloning vs pointer reference?

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

  

经常提到的PHP 5 OOP的一个关键点是“默认情况下通过引用传递对象”。这不完全正确。本节使用一些例子来纠正这种普遍的想法。

     

PHP引用是一个别名,它允许两个不同的变量写入相同的值。从PHP 5开始,对象变量不再包含对象本身作为值。它只包含一个对象标识符,允许对象访问者查找实际对象。当一个对象通过参数发送,返回或分配给另一个变量时,不同的变量不是别名:它们包含标识符的副本,它指向同一个对象。

如果对象是通过别名或处理程序传递的,那么您实际上希望通过引用传递什么情况?

myFunc($obj); // Pass by alias/handler

myFunc(& $obj); // Pass by reference (when would you do this?)

myFunc(clone $obj); // Create a new object

每种用例有哪些不同的用例?

3 个答案:

答案 0 :(得分:2)

  

每种用例有哪些不同的用例?

您已经命名了三种不同的用例:

  1. 将对象作为参数传递
  2. 将别名作为参数传递
  3. 将对象克隆作为参数传递
  4. 当你需要做特定案例时,你自然会做这三件事。你通常只需要1.99.9%。如果需要,你可以另外做0.1%。

    作为参数的变量别名的备用用例(在评论中要求)作为一个小例子(Demo):

    class VarFreezer
    {
        private $alias;
        private $value;
        public function __construct(&$object) {
            $this->alias = &$object;
            $this->value = $object;
        }
        public function restore()
        {
            $this->alias = $this->value;
        }
    }
    
    $var = new stdClass();
    $var->value = 'I am an object now.';
    
    $freezer = new VarFreezer($var);
    
    $var = 'I am a string now.';
    
    $freezer->restore();
    
    var_dump($var);
    

答案 1 :(得分:2)

当您为方法提供对象时,将传递对现有对象的引用,以便您在调用范围中具有变量,并且方法范围中的方法参数变量都引用同一对象。

您可以明确使用&提供对类似数组的原语的引用,以便调用的方法可以更改原始数组的数据。对于对象,这是您现在提到的默认值。

克隆似乎很明显。

使用& $ obj,您可以为$ obj创建一个别名,而不是对$ obj引用的对象的引用。引用php.net:

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

答案 2 :(得分:2)

myfunc($ obj)//传入标识符

当你的函数需要访问对象并以某种方式操作/读取它时。

myfunc(& $ obj)//传递对标识符的引用。

这里的关键是你传递对标识符的引用。这意味着如果外部变量($ obj)设置为null,那么内部对象也会变为null,因为您已从$ obj中删除了标识符,因此也删除了对它的引用。传递标识符的时候不同,因为你实际上在传递标识符的副本时传递的是什么,所以如果将$ obj设置为null,那么函数内部的值仍将指向该对象。

示例:

var x = new Object();

var y = x //y and x both contain **different** identifiers to the same object in memory.

function a($_a){} // a function for examples

a($y) // passes in a copy of $y so $_a (inside the function) is a third identifier pointing to th in memory object

a(& $y) // now $_a contains the **same** identifier as $y so if either is emptied then the other is also emptied. 

a(clone $y) //creates a new object identical to the first and passes in an identifier of the new object.
希望这很清楚。

如果您希望能够从函数内部修改或删除标识符并使​​其影响外部标识符变量,同时能够返回独立计算的值,则可以通过引用传递标识符。例如序列化一个对象,将其保存到文件中返回文件字符串,但也清除标识符,以便从内存中清除该对象。