Подтвердить что ты не робот

Что именно происходит при создании экземпляра с помощью "нового"?

Рассмотрим следующий код:

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:

Я пытаюсь посмотреть, как распределение памяти происходит, когда используется новый. Но сейчас слишком много других вещей, которые я должен сделать прямо сейчас. Надеюсь, что скоро опубликую полезное обновление. До тех пор вот ссылки на код, на который я смотрел:

4b9b3361

Ответ 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.

Надеюсь, что поможет