在 PHP 中,当 $foo = new Foo() 时,从技术上讲,$foo 是一个对象,还是 $foo 一个引用?
Posted
技术标签:
【中文标题】在 PHP 中,当 $foo = new Foo() 时,从技术上讲,$foo 是一个对象,还是 $foo 一个引用?【英文标题】:In PHP, when $foo = new Foo(), technically speaking, is $foo an object, or is $foo a reference? 【发布时间】:2011-04-26 21:00:51 【问题描述】:更新:在
http://php.net/manual/en/language.oop5.references.php
上面写着:
PHP5 OOP 的关键点之一是 经常提到的是“物 默认情况下通过引用传递”。 这并不完全正确。
这是为什么呢?以下是我不知道是否完全正确的原因:
我认为松散地说,foo 可以说是一个对象,或者类 Foo 的一个实例。
但是从技术上讲,foo 是否只是一个引用,在 Java 和 Ruby 中的方式完全相同,其中变量 foo
始终只是对一个对象的引用。
这就是为什么在 PHP 中,
function add($obj)
$obj->a++;
我们不是说“通过引用传递”,而是从技术上讲,我们是在传递一个值,也就是一个引用。因此,它是“通过 引用”,而不是“通过 引用”。
但是,如果我们在 PHP 中说 foo 是一个对象,那么我想“通过引用传递”是有道理的。这是真的吗? foo 据说是对对象的引用,而不是对象,所以这就是为什么我们只是“按值传递”?
【问题讨论】:
(相关) blog.golemon.com/2007/01/youre-being-lied-to.html 该页面上说明这一想法的第一段代码在 Java 或 Ruby 中是相同的行为,但我们仍将其称为 Java 或 Ruby 中的“对对象的引用”,不是吗? 相关文章有误。它说 PHP 引用不是引用,因为它们可以分配为指向另一个对象。引用是引用,一种表示指向对象的指针的构造。根据语言规范,您可以或不能更改参考。 C++ 引用不能更改。可以更改 Java、Ruby 和 PHP 引用。 @Vincent 虽然我知道fallacies of authority arguments,但应该注意Sara Golemon 是PHP 核心和PECL 贡献者,并且写过a book about writing PHP extensions,所以我倾向于相信她知道她在写什么。但请随时与她讨论。她博客中的 cmets 是开放的。 我不怀疑她对 PHP 的了解,因为每个 PHP 代码示例都是真实的,并且(简单地)解释了行为。我不同意一些句子的措辞,例如Notice now, that $b is still that original object. Had it been an actual reference with $a, it would have changed to a simple string as well.
这是错误的,并且基于与 C++ 相关的引用概念。 Java 引用例如像 PHP 一样工作并且是引用...
【参考方案1】:
所有对象在 PHP 5+ 中默认通过引用传递,在 PHP 5 之前通过引用传递您使用“&”运算符
这意味着如果你将一个对象传递给一个方法,那么引用就会被复制,而方法中的另一个变量将包含引用的副本。
因此,默认情况下您不会通过引用传递引用 :),因此您不能为包含引用副本的变量分配新值并影响原始引用。
【讨论】:
这是因为在正式的 PHP 文档中:php.net/manual/en/language.oop5.references.php 说 PHP5 OOP 的关键点之一是经常提到的“对象默认通过引用传递”。这并不完全正确。 您在答案中描述的不是按引用传递,而是按引用值传递。【参考方案2】:$foo
不是对象,而是引用。说$foo
是对象是错误的,$foo
是指向对象的引用。
引用是按值传递的,就像 PHP(Java 和 Ruby)中的任何其他参数一样,因此您不能直接分配引用来修改它,但是您可以在它所指向的对象上进行任何操作。
为了简化抽象,程序员有时会说“$foo
是一个对象”,这是错误的,但比说整个“$foo
是指向对象的引用”要容易。在许多情况下,差异实际上并不重要,除非在某些极端情况下。
【讨论】:
所以我猜php.net/manual/en/function.is-object.php is_object — 查找一个变量是否是一个对象——它的真正意思是“一个变量是否是一个对象的引用。” 是的。从来没有说过 PHP 文档是一致的 :)【参考方案3】:PHP 对象变量实际上并不包含对象(就像在许多其他语言中一样) - 它包含对象的“句柄” - 即允许识别对象、找到它并对其进行操作的某个值。这个变量像其他任何变量一样被传递 - 它可以通过-val、by-ref 等传递。但是,如果您将此值复制到另一个变量,则与整数或字符串发生的情况相同和不同。
整数/字符串:值被复制,所以当它被修改时,另一个保持不变。
对象:值被复制,但该值是一个句柄。因此,如果此句柄用于访问实际对象(这几乎是使用此句柄的唯一方法)并且此访问修改了它,那么另一个变量 - 独立但包含相同的句柄 - 将反映更改。
所以它实际上是非常一致的,只是有点不像你期望的那样天真地对待“按值”和“按引用”——因为对于标量和对象变量,传递的内容实际上是不同的。对象变量包括间接级别。
顺便说一句,这就是为什么通过引用传递对象变量几乎没有意义的原因 - 除非您想在函数中用另一个对象替换一个对象。
【讨论】:
这个“句柄”就是我们通常所说的“引用”或“指针” @newacct 不幸的是,在 PHP 中“引用”意味着别的东西,严格来说,它不是一个指针 - 它是特定对象处理程序的对象存储中的索引。以上是关于在 PHP 中,当 $foo = new Foo() 时,从技术上讲,$foo 是一个对象,还是 $foo 一个引用?的主要内容,如果未能解决你的问题,请参考以下文章
auto foo = ref new Foo();啥是“参考”?
`throw 'foo'`、`throw Error('foo')`、`throw new Error('foo')` 有啥区别?