【问题标题】:If Objects are passed by alias when would you pass by reference? [duplicate]如果对象通过别名传递,你什么时候通过引用传递? [复制]
【发布时间】:2012-07-18 19:30:54
【问题描述】:

可能重复:
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

这些都有哪些不同的用例?

【问题讨论】:

  • 我认为本次讲座涵盖了以下主题:youtube.com/watch?v=bxxIXPc9IR8(除其他外)
  • 注意,调用时传递引用至少从 5.3 开始被弃用,如果不是更早的话。该函数声明它期望哪些参数是引用,调用者不必指定它们是引用——事实上,不应该。

标签: php


【解决方案1】:

这些都有哪些不同的用例?

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

  1. 将对象作为参数传递
  2. 将别名作为参数传递
  3. 将对象克隆作为参数传递

当您需要执行特定案例时,您自然会执行这三件事中的每一件事。您通常只需要 1. in 99.9%。剩下的 0.1% 会在你需要的时候做。

一个变量别名作为参数的示例用例(在 cmets 中要求)作为一个小例子 (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);

【讨论】:

  • 知道myFunc(& $obj) 的具体用例是什么吗?
  • 那是专门传递一个变量别名作为参数。因此,您可以使用第二个名称引用相同的变量。
  • @Dev 我专门询问对象及其传递给函数时的行为——而不是像字符串这样的原语。
  • 如果你传递一个引用,它更多的是关于变量名而不是实际值。
  • @MikeB:我添加了一些示例代码,展示了这些别名的用途。
【解决方案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...

【讨论】:

    【解决方案3】:

    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.
    

    希望够清楚。

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

    【讨论】:

      猜你喜欢
      • 2013-11-24
      • 1970-01-01
      • 2015-06-18
      • 1970-01-01
      • 2017-09-11
      • 1970-01-01
      • 2019-03-02
      • 2019-09-01
      相关资源
      最近更新 更多