Я пытаюсь понять PHP zvals. Итак, рассмотрим следующий код:
<?php
$randomByteString = 'abcd';
$val = 0;
for ($i = 0; $i < 4; ++$i) {
$val |= ord($randomByteString[$i]) << ($i * 8);
}
echo $val;
Мне кажется, что zval будет создан для каждого из этих утверждений:
Это верно?
Не совсем. Давайте посмотрим на это построчно, рассказав, как PHP 5 будет обрабатывать эти звали.
<?php
$randomByteString = 'abcd';
Новый звал, содержащий 'abcd'
создан и сейчас $randomByteString
указывает на это.
Звал всего пока: 1
$val = 0;
Новый звал, содержащий 0
создан и сейчас $val
указывает на это.
Звала пока что: 2
for ($i = 0; $i < 4; ++$i) {
При первом запуске мы создаем zval для 0
и указать $i
к этому.
Сравнение $i
а также 4
может временно создать логическое значение zval. Моя память о том, что PHP 5 делает здесь, нечеткая, он может не делать этого скрытно. Это не имеет значения для нашего общего подсчета, потому что он будет немедленно отброшен.
Приращение $i
не создает zval, он просто меняет число внутри zval $i
уже указывает на.
Счет Zval до сих пор: 3 (не включая временный zval, поскольку он был выброшен)
$val |= ord($randomByteString[$i]) << ($i * 8);
Доступ к $randomByteString[$i]
создаст zval, содержащий однобайтовую строку. Передав это ord()
откажется от этого zval и создаст новый zval, содержащий целое число.
Умножая это 8
от $i
создаст новый zval.
Сдвиг влево наш ord()
результат нашим $i
Результат создаст новый zval и уберет два наших входных zval.
Наконец, используя |=
с $val
изменит значение в $val
и отбросим наш левый сдвиг. $val
уже существует, поэтому мы просто меняем содержимое, а не делаем новый zval для него.
Звала пока что: 4
}
echo $val;
Эхо не создаст звалс.
В конце сценария у вас есть 4 звали вокруг.
Кстати, zvals создан для $i < 4
, $randomByteString[$i]
, ($i * 8)
а также <<
являются все временный zvals: они не вызывают нового выделения памяти, вместо этого они хранятся в специальной области памяти, используемой для временных значений. Это означает, что при создании этих временных значений нет снижения производительности. Другие звалы (в том числе ord()
по какой-то причине вызовы функций неэффективны), с другой стороны, требуют выделения памяти.
Кроме того, это все только для PHP 5. PHP 7 обрабатывает zvals более разумно, поэтому обычно для них не требуется отдельное выделение памяти.
Других решений пока нет …