#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 { }
Комментариев нет:
Отправить комментарий