На прошлой неделе мы представили весь жизненный цикл переменных PHP с нижней точки зрения: генерация – > назначение констант – > уничтожение. (Студенты, которые не знают, могут ознакомиться с предыдущей статьей об основных принципах переменных PHP (1).) Но мы оставили мысль, не знаю, есть ли у вас ответ, и как добиться назначения между переменными внизу?
Назначение между переменными
Структура zval переменных PHP вводилась много раз, и мы не будем здесь делать больше. Но для структуры zval refcount__gc и is_ref__gc Поля никогда не были подробно описаны, и эти два поля тесно связаны с принципом присвоения между переменными. Итак, на этот раз мы начнем с нескольких примеров, чтобы понять изменения в этих двух областях и основные знания, которые они приносят.
Принцип копирования во время записи
Приведите пример:
A = Xu Zheng's technological growth path;
$b = $a;
xdebug_debug_zval("a", "b");Результат:
A: (refcount = 2, is_ref = 0) ='Xu Zheng's technological growth path' B: (refcount = 2, is_ref = 0) ='Xu Zheng's technological growth path'
Смотрите здесь, вы можете быть более монгольским. Разве это не присвоение переменной? Должна ли произойти копия значения? Почему количество ссылок на две переменные не 1, а 2?
Это связано с тем, что При разработке PHP для экономии памяти при назначении между переменными две переменные с одинаковым значением имеют общую память, то есть указатель переменной переменной B будет указывать на одну и ту же структуру zval переменной a в глобальной таблице символов, и только при изменении структуры zval переменной произойдет изменение памяти репликации контейнера переменных, что также называется репликацией контейнера переменных. do Принцип копирования во время записи
Когда это произойдет? Принцип копирования во время записи Как насчет этого?
Принцип копирования во время записи Время запуска: Когда PHP изменяет переменную, если он обнаруживает, что количество ссылок переменной больше 1, выполняется копирование контейнера переменной в память
Приведите пример:
A = Xu Zheng's technological growth path;
$b = $a; // At this point variable a and variable b point together to the same variable container, refcount > 1
$b = Xu Zheng's Way to Technological Growth 1 // Trigger Write-Time Replication Mechanism
xdebug_debug_zval("a", "b");Результат:
A: (refcount = 1, is_ref = 0) ='Xu Zheng's technological growth path' B: (refcount = 1, is_ref = 0) ='Xu Zheng's technological growth path 1'
Принцип Изменения Времени Записи
Распределение между переменными понятно. Как насчет распределения между переменными и ссылками? Мы также иллюстрируем это примерами.
Приведите пример:
A = Xu Zheng's technological growth path;
$b = &$a;
xdebug_debug_zval("a", "b");Результат:
A: (refcount = 2, is_ref = 1) ='Xu Zheng's technological growth path' B: (refcount = 2, is_ref = 1) ='Xu Zheng's technological growth path'
На этом этапе мы обнаруживаем, что количество ссылок на переменные A и B по-прежнему равно 2, но is_ref становится 1. Это связано с тем, что, когда переменная a упоминается и присваивается переменной b, она изменяется в контейнере исходной переменной, чтобы изменить is_ref на 1, а количество ссылок+1.
Что делать, если переменная изменяется на основе присвоения ссылки?
Приведите пример:
A = Xu Zheng's technological growth path;
$b = &$a;
$b = Xu Zheng's Road to Technological Growth 1
xdebug_debug_zval("a", "b");Результат:
A: (refcount = 2, is_ref = 1) ='Xu Zheng's technological growth path 1' B: (refcount = 2, is_ref = 1) ='Xu Zheng's technological growth path 1'
Ты думаешь, это удивительно? Переменная B изменяется со значением переменной a, потому что она запускает Принцип изменения времени записи
Принцип изменения времени записи Время срабатывания: Контейнеры переменных с is_ref, равным 1, должны сначала проверить, равен ли is_ref контейнеров переменных 1 перед назначением. Если значение равно 1, оно не будет копироваться во время записи, а будет вносить изменения в содержимое на основе исходных контейнеров переменных. Если контейнеры переменных с is_ref 1 назначены другим переменным, это немедленно сработает. Копирование во время записи
Так что, если мы объединим примеры, которые мы только что привели? Каков конечный результат?
Приведите пример:
A = Xu Zheng's technological growth path;
$b = $a;
$c = &$a;
xdebug_debug_zval("a", "b", "c");Результат:
A: (refcount = 2, is_ref = 1) ='Xu Zheng's technological growth path' B: (refcount = 1, is_ref = 0) ='Xu Zheng's technological growth path' C: (refcount = 2, is_ref = 1) ='Xu Zheng's technological growth path'
Весь процесс выполнения выглядит следующим образом: когда выполняется вторая строка, количество ссылок в контейнере переменных становится 2, переменная a и переменная B используют один и тот же контейнер переменных; когда выполняется третья строка, поскольку ссылка на переменную a назначена переменной c, но переменная B и переменная a уже используют один и тот же контейнер переменных, тогда контейнер переменных изменится, потому что число ссылок > 2. Когда переменные a и B разделены, а затем переменная ссылка назначена переменной c, исходный базис изменяется, is_ref становится 1, а число ссылок становится 2.
Отражение
Итак, каков конечный результат этого примера? Добро пожаловать, чтобы оставить сообщение или довериться мне ниже.~
Приведите пример:
A = Xu Zheng's technological growth path;
$b = $a;
$c = &$a;
$d = $a;
$e = Xu Zheng's Road to Technological Growth 1
$a = $e;
xdebug_debug_zval("a", "b", "c", "d", "e");Если вам понравилась моя статья, пожалуйста, похвалите меня и поддержите, и добро пожаловать, чтобы обратить внимание на мою колонку. Каждую неделю будут появляться оригинальные и подробные статьи.~