1
 class a {
public $test="msg1";
}          

 $t1 = new a;
 echo "echo1: After Instantiation :<br/>";
 xdebug_debug_zval('t1');echo "<br/><br/>";

 $t2 = $t1;
 echo 'echo2: After assigning $t1 to $t2 :<br/>';
 xdebug_debug_zval('t2');echo "<br/><br/>";

 $t1->test="msg2";
 echo 'echo3: After assigning $t1->test = "msg2" :<br/>';
 xdebug_debug_zval('t1');echo "<br/>";
 xdebug_debug_zval('t2');echo "<br/><br/>";

 $t2->test="msg3";
 echo 'echo4: After assigning $t2->test="msg3" :<br/>';
 xdebug_debug_zval('t1');echo "<br/>";
 xdebug_debug_zval('t2');echo "<br/><br/>"; 

 $t2->test2 = "c*ap!";
 echo 'echo5: After injecting $test2 to $t2 :<br/>';
 xdebug_debug_zval('t1');echo "<br/>";
 xdebug_debug_zval('t2');echo "<br/><br/>";

输出:

echo1: 实例化后:
t1: (refcount=1, is_ref=0)=class a { public $test = (refcount=2, is_ref=0)='msg1' }

echo2: 将 $t1 分配给 $t2 后:
t2: (refcount=2, is_ref=0)=class a { public $test = (refcount=2, is_ref=0)='msg1' }

echo3: 分配后 $t1->test = "msg2" :
t1: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg2' }
t2: ( refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg2' }

echo4: 分配后 $t2->test="msg3" :
t1: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg3' }
t2: ( refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg3' }

echo5: 将 $test2 注入 $t2 后:
t1: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg3'; public $test2 = (refcount=1, is_ref=0)='c ap!' }
t2: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg3'; public $test2 = (refcount=1, is_ref=0)='c
ap!' }

忽略echo1&echo2因为这个:用“新”实例化时到底发生了什么?& 预期的行为。

考虑echo3

echo3: 分配后 $t1->test = "msg2" :
t1: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg2' }
t2: ( refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg2' }

这是可以理解的,因为我只是更改$t1->test变量而不直接更改&t2->test.

考虑到echo4,在哪里进行直接更改$t2->test

echo4: 分配后 $t2->test="msg3" :
t1: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg3' }
t2: ( refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg3' }

没有奶牛发生!$t1即使is_ref未设置,更改也会反映到。

考虑echo5到变量$test2被注入的位置$t2

echo5: 将 $test2 注入 $t2 后:
t1: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg4'; public $test2 = (refcount=1, is_ref=0)='c ap!' }
t2: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg4'; public $test2 = (refcount=1, is_ref=0)='c
ap!' }

再一次,没有奶牛发生!$t1即使is_ref未设置,更改也会反映到。

Why is this behaviour!?

4

1 回答 1

2

确实如此,但你的期望是错误的。

该值是一个对象标识符。您将其分配给$t1or $t2。对象标识符在写入时被复制,但它仍然引用同一个对象,因此在您在问题中概述的任何情况下都不会复制该对象。

请参阅对象和参考文档

经常提到的 PHP 5 OOP 的关键点之一是“对象默认通过引用传递”。这并不完全正确。[...] 从 PHP 5 开始,对象变量不再包含对象本身作为值。它只包含一个对象标识符,允许对象访问者找到实际对象。

COW 是一种优化。PHP here 看到了这一点$t1->test,并且$t2->test实际上是相同的值。因此,如果您更改它,优化就会启动,因为根本没有什么可复制的。

于 2012-01-01T10:51:20.673 回答