Почему COW не происходит, когда «запись в свойство» / «внедрение свойства в объект» класса? - PullRequest
1 голос
/ 01 января 2012
 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) = класс 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) = 'c ap!' }
t2: (refcount = 2, is_ref = 0) = класс a {public $ test = (refcount = 1, is_ref = 0) = 'msg3'; public $ test2 = (refcount = 1, is_ref = 0) = 'c
ap!' }

Игнорирование echo1 & echo2 из-за этого: Что именно происходит при создании экземпляра 'new'? и ожидаемого поведения.

Учитывая 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'}

Нет C.O.W! и изменение также отражается в $t1, даже если is_ref не установлено.

Учитывая 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) = 'c ap!' }
t2: (refcount = 2, is_ref = 0) = класс a {public $ test = (refcount = 1, is_ref = 0) = 'msg4'; public $ test2 = (refcount = 1, is_ref = 0) = 'c
ap!' }

Опять же, нет C.O.W! и изменение также отражается в $t1, даже если is_ref не установлено.

Why is this behaviour!?

1 Ответ

2 голосов
/ 01 января 2012

Да, но вы ошибаетесь.

Значение является идентификатором объекта.Вы назначаете это $t1 или $t2.Идентификатор объекта копируется при записи, но он по-прежнему ссылается на тот же объект, поэтому объект не копируется ни в одном из случаев, которые вы наметили в своем вопросе.

См. Объекты иссылки Документы :

Один из ключевых моментов ООП PHP 5, который часто упоминается, заключается в том, что "объекты передаются по ссылкам по умолчанию".Это не совсем верно.[...] Начиная с PHP 5, переменная объекта больше не содержит сам объект в качестве значения.Он содержит только идентификатор объекта, который позволяет методам доступа к объекту найти фактический объект.

COW - это оптимизация.Здесь PHP видит, что $t1->test и $t2->test на самом деле имеют одинаковое значение.Поэтому, если вы измените его, оптимизация вступит в силу в том смысле, что копировать вообще нечего.

...