Что именно происходит при создании экземпляра с помощью "нового"?
Рассмотрим следующий код:
class a {
public $var1;
function disp(){
echo $this->var1;
}
}
$obj1 = new a;
echo '<br/>After instantiation into $obj1:<br/>';
xdebug_debug_zval('obj1');
$obj1->var1 = "Hello ";
echo '<br/><br/>After assigning "Hello" to $obj->var1:<br/>';
$obj1->disp();
echo "<br/><br/>";
xdebug_debug_zval('obj1');
Выход:
После создания экземпляра в $obj1:
obj1: (refcount = 1, is_ref = 0) = class a {public $var1 = (refcount = 2, is_ref = 0) = NULL}
После назначения" Hello "в $obj- > var1:
Hello
obj1: (refcount = 1, is_ref = 0) = class a {public $var1 = (refcount = 1, is_ref = 0) = 'Hello'}
Один за другим:
После создания экземпляра в $obj1:
obj1: (refcount = 1, is_ref = 0) = class a {public $var1 = (refcount = 2, is_ref = 0) = NULL}
Почему $obj1->var1
имеет refcount=2
, когда есть только один объект класса a?
Это из-за того, как оператор new
выполняет присвоение?
PHP выполняет задание со ссылками. При создании экземпляра с помощью new
имя символа/переменной не ассоциируется с этим экземпляром. Но свойства класса имеют имена. Из-за этого существует recount=2
?
Если это так, то CO.W(копирование при записи) произошел с неглубокой копией WRT экземпляра класса. Хотя свойства все еще указывают на zval свойств, созданных во время создания, используя new
.
Теперь,
После назначения "Hello "в $obj- > var1:
Hello
obj1: (refcount = 1, is_ref = 0) = class a {public $var1 = (refcount = 1, is_ref = 0) = 'Hello'}
Итак, когда я присваиваю значение свойству $obj1->var1
новый контейнер zval для этого свойства и, следовательно, refcount=1
?
Означает ли это, что контейнер zval, созданный во время создания экземпляра с помощью new
, все еще живет, но не может быть доступен, поскольку нет ассоциированного с ним символа/переменной?
Обратите внимание (от xdebug: переменные функции отображения):
debug_zval_dump()
отличается от xdebug_debug_zval()
.
void xdebug_debug_zval ([string varname [,...]])
Отображает информацию о переменной.
Эта функция отображает структурированную информацию об одной или нескольких переменных, которая включает в себя информацию о типе, значении и пересчете. Массивы исследуются рекурсивно со значениями. Эта функция реализована иначе, чем функция PHP debug_zval_dump(), чтобы обойти проблемы, которые имеет эта функция, поскольку сама переменная фактически передается функция. Версия Xdebug лучше, так как она использует имя переменной для поиска переменной во внутренней таблице символов и позволяет получить доступ ко всем свойствам напрямую, не имея дело с фактической передачей переменной функции. В результате информация, возвращаемая этой функцией, намного точнее, чем функция PHP для отображения информации zval.
UPDATE
: Dec 31th 2011:
Я пытаюсь посмотреть, как распределение памяти происходит, когда используется новый. Но сейчас слишком много других вещей, которые я должен сделать прямо сейчас. Надеюсь, что скоро опубликую полезное обновление. До тех пор вот ссылки на код, на который я смотрел:
Ответы
Ответ 1
Добавление другого экземпляра $obj2 = new a;
увеличивает refcount до 3, а не 4, поэтому это происходит в результате вызова xdebug_debug_zval. Цель функции xdebug состоит в том, чтобы избежать путаницы от передачи переменной в функцию и (возможно) создания дополнительной ссылки.
К сожалению, это не относится к переменным-членам; для этих zval создается другая ссылка для их экспорта. Таким образом, все предостережения и запутывающие обстоятельства, перечисленные в примечании debug_zval_dump документации, по-прежнему применяются для переменных-членов.
Ответ 2
Я думаю, что в разделе "Примечание: остерегайтесь пересчета" на следующей странице объясняется следующее:
http://php.net/manual/en/function.debug-zval-dump.php
Это показывает, что счетчик ссылок увеличивается, если zend оптимизирует, как он прошел, но тогда возникает "оговорка" при вызове copy-on-write, возвращая refcount обратно до 1.
Надеюсь, что поможет