为什么 COW 不会在以下情况发生:写入属性/ '将属性注入到对象中'班级?
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)='cap!' }
t2: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg3'; public $test2 = (refcount=1, is_ref=0)='cap!' }
echo1 & echo2
因为这个: 到底发生了什么当用“new”实例化时? &预期的行为。
考虑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' }
没有发生 COW!即使未设置 is_ref
,更改也会反映到 $t1
中。
考虑 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)='cap!' }
t2: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg4'; public $test2 = (refcount=1, is_ref=0)='cap!' }
,没有发生 COW!即使未设置 is_ref
,更改也会反映到 $t1
中。
为什么会出现这种行为!?
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/>";
The output:
echo1: After Instantiation :
t1: (refcount=1, is_ref=0)=class a { public $test = (refcount=2, is_ref=0)='msg1' }echo2: After assigning $t1 to $t2 :
t2: (refcount=2, is_ref=0)=class a { public $test = (refcount=2, is_ref=0)='msg1' }echo3: After assigning $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: After assigning $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: After injecting $test2 to $t2 :
t1: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg3'; public $test2 = (refcount=1, is_ref=0)='cap!' }
t2: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg3'; public $test2 = (refcount=1, is_ref=0)='cap!' }
Ignoring echo1
& echo2
because of this: What is exactly happening when instantiating with 'new'? & expected behaviour.
Considering echo3
:
echo3: After assigning $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' }
This is understandable as I am just changing $t1->test
variable and no direct change to &t2->test
.
Considering echo4
, where a direct change to $t2->test
is done:
echo4: After assigning $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' }
No C.O.W takes place! and the change is reflected to $t1
as well even though is_ref
is not set.
Considering echo5
, where the variable $test2
is injected into $t2
:
echo5: After injecting $test2 to $t2 :
t1: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg4'; public $test2 = (refcount=1, is_ref=0)='cap!' }
t2: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg4'; public $test2 = (refcount=1, is_ref=0)='cap!' }
Again, no C.O.W takes place! and the change is reflected to $t1
as well even though is_ref
is not set.
Why is this behaviour!?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
确实如此,但您的期望是错误的。
该值是一个对象标识符。您将其分配给
$t1
或$t2
。对象标识符在写入时被复制,但它仍然引用同一个对象,因此在您在问题中概述的任何情况下都不会复制该对象。请参阅对象和引用文档 :
COW是一种优化。 PHP 在这里看到
$t1->test
和$t2->test
实际上是相同的值。因此,如果您更改它,优化就会启动,因为根本没有任何内容可以复制。It does but you're having the wrong expectation.
The value is an object identifier. You assign that to
$t1
or$t2
. The object identifier is copied on write, but it still refers to the same object, so the object isn't copied in any of the cases you outline in your question.See Objects and referencesDocs:
C.O.W. is an optimization. PHP here sees that
$t1->test
and$t2->test
are actually the same value. So if you change it, the optimization kicks in in the sense that there is nothing to copy at all.