Что определяет, когда объект класса уничтожается в PHP?
предположим, что у нас есть класс CFoo
. В следующем примере when is CFoo::__destruct()
называется?
function MyPHPFunc()
{
$foo = new CFoo();
. . .
// When/where/how does $foo get destroyed/deleted?
}
в этом примере деструктор будет вызываться, когда скрипт выходит из области MyPHPFunc
, потому что $foo
больше не будет доступна?
5 ответов
в PHP все значения сохраняются в так называемом zval
s. Те zval
s содержат фактические данные, введите информацию и-это важно для вашего вопроса-счетчик ссылок. Посмотрите на следующий фрагмент:
$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
ing a переменная:$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
ed). В этом случае порядок уничтожения является неопределенным поведением.
PHP 5 вводит концепцию деструктора, аналогичную другой объектно-ориентированные языки, такие как C++. Метод деструктора будет вызывается, как только нет других ссылок на конкретный объекта, или в любом порядке во время выключения. - руководство по PHP
Если вы хотите увидеть процесс в действии, вы можете запустить этот код.
<?php
class A
{
public function __construct() { var_dump('Creating: '. get_class($this)); }
public function __destruct() { var_dump('Removing: '. get_class($this)); }
}
class B extends A {}
$A = new A();
/*
* When this block is called later on
*/
function create_b()
{
$B = new B();
} // At this point the function scope ends, and since $B is not referenced anymore it's removed.
var_dump('B is next');
create_b(); // Run above block, create, then destroy be
var_dump('B is now gone');
// At this point the PHP file parser ends, $A is destroyed since it's not used anymore
информация руководство, хотя и несколько загадочным:
PHP 5 вводит концепцию деструктора, аналогичную концепции других объектно-ориентированных языков, таких как C++. Метод деструктора будет вызван, как только не будет других ссылок на конкретный объект или в любом порядке во время последовательности завершения работы.
значение: деструктор будет вызываться, когда объект будет уничтожен (= например,unset()
), или когда сценарий закрыть.
дополнительная информация:
Как и конструкторы, родительские деструкторы не будут вызываться неявно двигателем. Чтобы запустить Родительский деструктор, нужно было бы явно вызвать parent::__destruct() в теле деструктора.
деструктор будет вызываться, даже если выполнение скрипта остановлено с помощью exit(). Вызов exit () в деструкторе предотвратит выполнение оставшихся процедур завершения работы.
лучший способ узнать-проверить.
однако простой ответ заключается в том, что __destruct вызывается во время очистки мусора. Грубый, который никому не помогает, поскольку очистка мусора-это непрерывный процесс, который очищает локальные переменные, когда нет области, которая может их вызвать.
однако вот пример кода и результат, который полностью объясняет, что происходит при выходе из области внутренне в скрипт.
<?php
class testingdestructor {
public function __construct($num) {
$this->num = $num;
}
public function __destruct() {
echo "I am number {$this->num}\n";
}
}
class testing2{
public function __construct($num) {
$this->classtest = new testingdestructor($num);
}
public function __destruct() {
echo "I am not a number\n";
}
}
$iam1 = new testingdestructor(1);
$iam4 = new testing2(4);
function testfunction() {
$iam2 = new testingdestructor(2);
}
testfunction();
$iam3 = new testingdestructor(3);
unset($iam1);
выход из этого странного набора классы функции и vars это
I am number 2
I am number 1
I am number 3
I am not a number
I am number 4
это показывает нам, что конец функции вызывает __destruct, как и unset, и что, по крайней мере, на практике этот конец очистки скрипта выполняется в обратном порядке.
Если создать экземпляр класса и использовать объект.после завершения всех ваших задач, если u вызовет деструктор и снова использует тот же объект в следующей строке для выполнения какой-либо другой задачи, u больше не сможет использовать. Это означает, что UR destructor вызывается успешно