В PHP все значения сохраняются в так называемых zval
с.Эти zval
содержат фактические данные, информацию о типе и - это важно для вашего вопроса - счетчик ссылок.Взгляните на следующий фрагмент:
$a = new B; // $a points to zval(new B) with refcount=1
$b = $a; // $a, $b point to zval(new B) with refcount=2 (+1)
$c = $b; // $a, $b, $c point to zval(new B) with refcount=3 (+1)
unset($a); // $b, $c point to zval(new B) with refcount=2 (-1)
Как только refcount
достигает 0
, zval
освобождается и вызывается деструктор объекта.
Вот некоторыепримеры refcount
достижения 0
:
unset
использования переменной:
$a = new B; // refcount=1
unset($a); // refcount=0 => __destruct!
Но:
$a = new B; // refcount=1
$b = $a; // refcount=2
unset($a); // refcount=1 => no destruct as refcount > 0, even though unset() was called!
область выхода из функции (или метода)
function a() {
$a = new B; // refcount=1
} // refcount=0 => __destruct! (as $a does not exist anymore)
конец выполнения скрипта
$a = new B; // refcount=1
die(); // refcount=0 => __destruct! (on script execution end all vars are freed)
// doesn't need to be die(), can be just normal execution end
Это, очевидно, невсе условия, приводящие к сокращению refcount
, но те, которые вы будете чаще всего встречать.
Также я должен упомянуть, что, поскольку в PHP 5.3 также будут обнаруживаться циклические ссылки.Поэтому, если объект $a
ссылается на объект $b
и $b
, ссылается на $a
, и нет никаких дальнейших ссылок на $a
или $b
, то refcount
s обоих будут 1
, но онивсе еще будет освобожден (и __destruct
ред).В этом случае порядок уничтожения не определен.