Страницы

Поиск по вопросам

пятница, 24 января 2020 г.

Переменная ссылается на саму себя

#php


Прочитал я достаточно много статей о том как устроены переменные внутри машины Zend
и узнал одну интересную вещь, которую не могу объяснить:

$int = 100;
xdebug_debug_zval('int');/// int:(refcount=1, is_ref=0),int 100
$int = &$int;
xdebug_debug_zval('int');/// int:(refcount=1, is_ref=1),int 100


Как получается так что мы создаем ссылку саму на себя? Как это вообще возможно?
Подобного не видел, если и будете ставить минусы то аргументируйте пожалуйста свой выбор.

Небольшая информация из того что я знаю:

Как правило is_ref=1 только в том случае когда на zval контейнер ссылается 2 и более
переменные жесткой ссылкой.

refcount - это количество переменных ссылающихся на один и тот же zval контейнер,
но разница в том что refcount по разному работает с is_ref=0 и is_ref=1.

Если is_ref=0, а refcount > 1 то при создании жестких ссылок создается новый zval
 контейнер, если мы делаем присвоение по значению то новый zval не создается, а используется
старый.

Если is_ref=1, а refcount > 1 то при создании жестких ссылок новый zval не создается,
а используется старый, но если мы не создаем жесткую ссылку, а присваиваем по значению
то создается новый zval контейнер.

P.S Я написал это для того, чтобы показать что прекрасно понимаю, что я спрашиваю,
а также показываю почему мне непонятно поведение кода, которое я написал выше.

P.S Феерично


  Отметим, что если "refcount" равен 1, то "is_ref" будет всегда равен
  FALSE.
  http://php.net/manual/ru/features.gc.refcounting-basics.php

    


Ответы

Ответ 1



Внутри структуры zval не хранится имя символа, который отсылает к ней. Это легко увидеть из определения zval. Сам символ (имя переменной) хранится отдельно в символьной таблице. Таким образом то, какие флаги отмечены внутри zval, и то, как вы её называете - разные сущности. Название (символ) для переменной - это одно. Что хранится внутри переменной, включая всевозможные флаги - это другое. Благодаря этому может быть много переменных имеющих одно и то же имя. Например, может быть внешняя относительно функции переменная $int, имеющая одно значения, и может быть внутренняя для функции переменная $int, имеющая как другое значение, так и может быть одноименная переменная ссылающаяся на то же самое значение что и ранее упомянутая переменная $int. Это реализуется в виде символьных таблиц соответствия символов и значений zval для каждой области видимости. В вашем примере первый символ (или имя переменной) $int - это не то же самое что второй символ $int. Хоть они оба отсылают к одной zval в тот момент когда вы на них смотрите, в момент создания первый $int был просто числом, а второй - был уже ссылкой. Второй уже был ссылкой до того как вы его назвали, присвоив символу $int. Для примера, ниже $a и $b отличаются от ваших двух $int лишь именем, а значит у zval в PHP 7 уже будет две ссылки: $a = 100; xdebug_debug_zval('a'); // a: (refcount=0, is_ref=0)=100 $b = &$a; xdebug_debug_zval('b'); // b: (refcount=2, is_ref=1)=100 xdebug_debug_zval('a'); //a: (refcount=2, is_ref=1)=100 Для сравнения, ваш же вариант в PHP 7: $int = 100; xdebug_debug_zval('int'); // int: (refcount=0, is_ref=0)=100 $int = &$int; xdebug_debug_zval('int'); //int: (refcount=1, is_ref=1)=100 Очевидно, в PHP 7 несколько иное отношение к исходному значению refcount для простейших. Для объектов всё как было: $int = new stdClass(); xdebug_debug_zval('int'); // int: (refcount=1, is_ref=0)=class stdClass { } $int = &$int; xdebug_debug_zval('int'); // int: (refcount=1, is_ref=1)=class stdClass { }

Комментариев нет:

Отправить комментарий