通过引用传递;为啥原始对象没有改变?

Posted

技术标签:

【中文标题】通过引用传递;为啥原始对象没有改变?【英文标题】:Passing by reference; why is the original object not changed?通过引用传递;为什么原始对象没有改变? 【发布时间】:2011-09-04 02:59:54 【问题描述】:

如果在 php5 中对象是通过引用传递的,那么为什么下面的 $foo 不会改变?

$foo = array(1, 2, 3);
$foo = (object)$foo;

$x = $foo;            // $x = &$foo makes $foo (5)!
$x = (object)array(5);

print_r($foo); // still 1,2,3

所以:

引用传递不一样 分配。

那为什么下面的$foo(100, 2, 3)

$foo = array('xxx' => 1, 'yyy' => 2, 'zzz' => 3);
$foo = (object)$foo;

$x = $foo;            
$x->xxx = 100;

print_r($foo);

【问题讨论】:

还有,这不是很混乱吗?我的意思是我不认为将对象分配给变量的人期望对象会改变......除非他们真的知道 PHP 会这样做...... 再一次:“通过引用传递”通常意味着通过某个地方。这只是常用词。 Tomalak 已经解释过——在第一种情况下,我们有一个副本 对象的引用分配是非常混乱的!一个演员给你一个新的对象不是。 Alex,在 PHP 中,没有什么是永远通过引用传递(或通过引用分配),除非 PHP 被告知这样做。对象以 reference-like 方式处理(因为 object 的 zvals 只存储对对象数据的引用),但绝不是真正的引用。 【参考方案1】:

问题出在这里:

$x = $foo;   
$x = (object)array(5);

在第一条规则中,$x 被引用到 $foo;编辑 $x 也会编辑 $foo;(这称为“通过引用分配”,而不是“通过引用传递”*1)

$x->myProperty= "Hi";

将导致 $foo 也有一个属性“myProperty”。

但在下一行,您将 $x 引用到 new 对象。 有效地从 $foo 中取消引用 $x,您对 $x 所做的所有更改都不会传播到 $foo。

*1:当你调用一个函数时,你传递给函数的对象是(在php5中)“通过引用传递”

【讨论】:

好的,所以分配和通过引用都可以工作,但对我来说,如果没有 &,通过引用分配感觉“不自然”。如果我想要一个对象的副本怎么办:P 我阅读了其他正确答案,但仍然看不到我错过了什么。 +1 以获得清晰和简单的解释。 @Alex:你必须克隆它。 $copy = 克隆 $original;详情请见php.net/manual/en/language.oop5.cloning.php。 @Alex:我同意。 PHP 通过引用分配对象的策略让我的皮肤爬行。【参考方案2】:

不仅对象是通过引用传递的; they are also assigned by reference(这就是你真正在说的):

在 PHP 中通常的按值赋值行为有一个例外,对象是在 PHP 5 中按引用分配的。

但是,在您的第一个示例中,您正在执行强制转换操作。 This entails a copy:

如果将任何其他类型的值转换为对象,则会创建 stdClass 内置类的新实例

数组在 PHP 中有自己的类型,而不是对象;因此上述规则适用。

【讨论】:

是的,演员给了我们一份副本——而不是参考。但是主要OP的误解在于“通过引用传递”,这不在提供的代码中。 @gaRex:我知道。我不会说这是“主要”误解,但这肯定是一个因素。【参考方案3】:

引用传递与赋值不同。

【讨论】:

简洁不能代替彻底。 我更喜欢给鱼而不是鱼。 -1 实际上,事实证明这是错误的。 PHP5 也通过引用来分配对象。 是的,你在写。但在这个具体的例子中这是不可能的。 @gaRex:不。引用分配发生得很好。让 OP 脱轨的是演员阵容。【参考方案4】:

首先,您通过将数组转换为对象来创建对象。然后创建变量并通过引用传递该对象。但它不起作用,因为在那之后您将一些其他对象(从新数组转换)分配给第二个变量。

结果是对第二个对象的引用改变了,第一个对象本身没有改变。

查看Objects and References的更多详情。

【讨论】:

$foo 是一个数组,而不是一个对象。 啊,在演员阵容之后,当然。抱歉,来晚了。 “起初”它是一个数组,而不是一个对象。 @Tomalak 好的,我已经更改了答案,所以现在可能更清楚了。

以上是关于通过引用传递;为啥原始对象没有改变?的主要内容,如果未能解决你的问题,请参考以下文章

java参数传递(值传递还是引用传递)

Java 值传递和引用传递

参数传递(值传递与引用传递)

为啥这个对象在分配其他东西时不通过引用传递?

JavaScript - 通过引用传递时清空数组/对象问题

C# 通过引用传递属性