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-&gt; 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-&gt; 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
&amp; echo2
因此:What is exactly happening when instantiating with 'new'?&amp;预期的行为。
考虑echo3
:
echo3:分配$ t1-&gt; 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-&gt; 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'}
没有C.O.W发生! <!1}}即使未设置$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!' }
再次,没有C.O.W发生! <!1}}即使未设置$t1
,也会将更改反映到is_ref
。
Why is this behaviour!?
答案 0 :(得分:2)
确实如此,但你有错误的期望。
该值是对象标识符。您可以将其分配给$t1
或$t2
。对象标识符在写入时复制,但它仍然引用同一个对象,因此在您在问题中概述的任何情况下都不会复制该对象。
请参阅Objects and referencesDocs:
经常提到的PHP 5 OOP的一个关键点是&#34;对象默认通过引用传递&#34;。这不完全正确。 [...]从PHP 5开始,对象变量不再包含对象本身作为值。它只包含一个对象标识符,允许对象访问者查找实际对象。
C.O.W。是一种优化。 PHP在这里看到$t1->test
和$t2->test
实际上是相同的值。因此,如果你改变它,那么优化就会在没有任何东西可以复制的情况下发挥作用。