Php 为什么在';写入属性';/';将属性注入对象';什么课? a类{ public$test=“msg1”; } $t1=新a; echo“echo1:实例化后:”; xdebug_debug_zval('t1');回声“”; $t2=$t1; echo“echo2:将$t1分配给$t2后:”; xdebug_debug_zval('t2');回声“”; $t1->test=“msg2”; echo“echo3:在分配$t1->test=“msg2”之后:; xdebug_debug_zval('t1');回声“”; xdebug_debug_zval('t2');回声“”; $t2->test=“msg3”; echo'echo4:在分配$t2->test=“msg3”之后:; xdebug_debug_zval('t1');回声“”; xdebug_debug_zval('t2');回声“”; $t2->test2=“c*ap!”; echo“echo5:在将$test2注入$t2之后:”; xdebug_debug_zval('t1');回声“”; xdebug_debug_zval('t2');回声“”;

Php 为什么在';写入属性';/';将属性注入对象';什么课? a类{ public$test=“msg1”; } $t1=新a; echo“echo1:实例化后:”; xdebug_debug_zval('t1');回声“”; $t2=$t1; echo“echo2:将$t1分配给$t2后:”; xdebug_debug_zval('t2');回声“”; $t1->test=“msg2”; echo“echo3:在分配$t1->test=“msg2”之后:; xdebug_debug_zval('t1');回声“”; xdebug_debug_zval('t2');回声“”; $t2->test=“msg3”; echo'echo4:在分配$t2->test=“msg3”之后:; xdebug_debug_zval('t1');回声“”; xdebug_debug_zval('t2');回声“”; $t2->test2=“c*ap!”; echo“echo5:在将$test2注入$t2之后:”; xdebug_debug_zval('t1');回声“”; xdebug_debug_zval('t2');回声“”;,php,reference,php-internals,Php,Reference,Php Internals,输出: echo1:实例化后: t1:(refcount=1,is_ref=0)=a类{public$test=(refcount=2,is_ref=0)='msg1'} echo2:将$t1分配给$t2后: t2:(refcount=2,is_ref=0)=a类{public$test=(refcount=2,is_ref=0)='msg1'} echo3:在分配$t1->test=“msg2”后: t1:(refcount=2,is_ref=0)=a类{public$test=(refcou

输出:

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

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

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

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

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

忽略
echo1
echo2
,原因是:&预期行为

考虑到echo3:

echo3:在分配$t1->test=“msg2”后:
t1:(refcount=2,is_ref=0)=a类{public$test=(refcount=1,is_ref=0)='msg2'}
t2:(refcount=2,is_ref=0)=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)=a类{public$test=(refcount=1,is_ref=0)='msg3'}
t2:(refcount=2,is_ref=0)=a类{public$test=(refcount=1,is_ref=0)='msg3'}

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

考虑到
echo5
,其中变量
$test2
被注入
$t2

echo5:将$test2注入$t2后:
t1:(refcount=2,is_ref=0)=a类{public$test=(refcount=1,is_ref=0)='msg4';public$test2=(refcount=1,is_ref=0)='cap!'
t2:(refcount=2,is_-ref=0)=a类{public$test=(refcount=1,is_-ref=0)='msg4';public$test2=(refcount=1,is_-ref=0)='cap!'

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


为什么会有这种行为

确实如此,但您的预期是错误的

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

见:

PHP5OOP中经常提到的一个关键点是“默认情况下对象是通过引用传递的”。这并不完全正确。[…]从PHP5开始,对象变量不再包含对象本身作为值。它只包含一个允许对象访问器查找实际对象的对象标识符


C.O.W.是一种优化。PHP在这里看到
$t1->test
$t2->test
实际上是相同的值。因此,如果您对其进行更改,则优化将从根本不需要复制的意义上开始。

当分配完成时,由于两者都指向同一个zval容器,因此更改将得到反映。拥有
参考赋值的要点是,如果$t1=新的a$t2=和$t1,$t2=新b;现在,$t1和$t2都将指向b类对象的zval容器?
$t2=&$t1
将使
$t2
成为
$t1
的别名。因此,您可以使用两个变量名来访问相同的值。两者都指同一个zval容器。另请参见,其中显示了创建引用(任何类型,而不仅仅是对象)时发生的情况。但是请注意,对象“值”表示为bespoken对象标识符。Hmmmmm。我已经阅读了refcounting基础知识,即使有您的解释,在我的脑海中仍然不清楚:(但是,感谢您的帮助。如果您真的想完全深入了解该理论:PHP如何在内部管理这些结构,这可能很有趣:
 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/>";