PHP按引用传递

3

请问以下代码中的"&"是什么意思:

class TEST {

}

$abc =& new TEST();

我知道它是通过引用实现的。但是有人能说明一下为什么以及何时需要这样做吗?或者指点我一个解释得很好的网址。我无法理解这个概念。
非常感谢。
5个回答

11

据我所知,您询问的不是关于PHP引用的一般性问题,而是关于$foo =& new Bar();构造习语的问题。

这种构造习语只存在于PHP4中,通常的$foo = new Bar()将存储对象的一个副本。这通常不会被注意到,除非类在构造函数中存储了对$this的引用。当稍后对返回的对象调用方法时,会存在两个不同的对象副本,而意图可能只是要一个副本。

考虑以下代码,其中构造函数将对$this的引用存储在全局变量中:

class Bar {
    function Bar(){
       $GLOBALS['copy']=&$this;
        $this->str="hello";
    }

}

//store copy of constructed object
$x=new Bar;
$x->str="goodbye";

echo $copy->str."\n"; //hello
echo $x->str."\n"; //goodbye

//store reference to constructed object
$x=&new Bar;
$x->str="au revoir";

echo $copy->str."\n"; //au revoir
echo $x->str."\n"; //au revoir
在第一个例子中,$x 和 $copy 引用了不同的 Foo 实例,但在第二个例子中它们是相同的。

谢谢您的回答。就实际情况而言,我认为我不需要使用 =& new... 因为我没有在任何地方存储 &$this。我的理解正确吗? - Alec Smart
没错。性能有轻微提升,但如果你想用php5的风格编写php4代码,我不会麻烦自己养成这个习惯。 - Paul Dixon

1
首先,如果您使用的是 PHP 5,您实际上不需要使用它,在 PHP 5 中默认情况下所有对象都是通过引用传递的。
其次,当您将一个对象分配给一个变量名时,无论是通过创建,传递参数还是设置变量值,您要么是按引用传递,要么是按值传递。
按引用传递意味着您传递对象的实际内存引用,因此如果您将对象作为参数传递给函数,则该函数对该变量所做的任何更改也将反映在父方法中,您实际上正在更改该对象在内存中的状态。
另一种选择,按值传递意味着您传递该对象的副本,而不是内存引用,因此您所做的任何更改都不会反映在原始对象中。

但是在这里我正在创建一个新对象...那么&的意义是什么? - Alec Smart
好的,你告诉PHP当创建新对象时,你希望PHP将这个新对象的内存地址分配给$abc变量。这现在是PHP的默认行为。 - Sam Cogan
1
@Sam_Cogan:不完全是这样的,请查看http://www.php.net/manual/en/language.oop5.references.php。 - Christoph

1

PHP手册做了相当不错的解释关于引用(references)。

需要注意的是,它们与指针或其他许多语言中的引用(reference)不是同一件事情,尽管存在相似之处。至于默认情况下对象被“按引用传递”的说法——这也不完全正确。

我建议首先阅读手册部分(并可能会反复阅读几次,直到理解为止),然后如果仍有更多问题,请再回到这里。


0
可能有助于将其理解为:在 PHP 中,所有变量实际上都是某种指针:符号表中的条目(将变量名称映射到值的东西)包含 Zend 引擎 C 实现中的 zval *
在赋值期间 - 这包括设置函数参数 - 将发生奇妙的事情:
如果你做 $a = $b,那么将创建一个指向符号表条目中 $b 所指向的值的副本,并将指向此新值的指针放置在 $a 的符号表条目中。现在,$a$b 将指向不同的值。PHP 将此用作其默认调用约定。
如果您执行$a =& $b,则$a的符号表条目将设置为包含在$b符号表条目中的指针。这意味着$a$b现在指向相同的值 - 直到程序员重新绑定它们之前,它们都是彼此的别名。还要注意$a实际上并不是$b的引用 - 它们都是指向同一对象的指针。
这就是为什么称它们为“别名”可能是一个好主意,以强调与C++的引用实现的区别:
在C++中,包含值的变量和从该变量创建的引用不相等 - 这就是为什么会出现悬空引用之类的东西的原因。
明确一点:在PHP中没有像引用类型这样的东西,因为所有变量都已内部实现为指针,因此它们中的每一个都可以充当引用。

PHP5对象仍然与此描述一致 - 它们不是按引用传递,而是传递一个指向对象的指针(手册称其为“对象标识符” - 它可能没有实际实现为C指针 - 我没有检查这个)通过值传递(意味着在分配时复制如上所述)。

请查阅手册以获取有关PHP5对象和引用之间关系的详细信息


其实,那是一个相当糟糕和误导性的解释。在 PHP 中,引用并不是指针。引用意味着引用的值将始终是所引用变量的值 - 即使它改变了。这相当令人困惑。 - troelskn
实际上,据我所知,PHP 中的符号表(将变量名映射到值的东西)包含指向 zval 的指针(zval 是 zend 中用于 PHP 值的类型)。因此,每个变量实际上都是指针!我可以稍微澄清一下这个问题... - Christoph
@troelskn:最后的编辑应该清楚地说明了“引擎盖下”实际发生了什么。 - Christoph

0
一种更简单的方法是这样看待它:
$a = 'foo';
$b = 'bar';
$a =& $b;
$b = 'foobar';
echo $a . ' ' . $b;

将输出

foobar foobar

什么鬼?你确定这个能用吗?O_o另外 - 这是 PHP4 的代码。 - Vilx-
不过我正在运行PHP5,所以无法检查,我将其删除并选择了我知道可行的示例。 - UnkwnTech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接