Что определяет, когда объект класса уничтожается в PHP?

предположим, что у нас есть класс CFoo. В следующем примере when is CFoo::__destruct() называется?

function MyPHPFunc()
{
  $foo = new CFoo();

  . . .

  // When/where/how does $foo get destroyed/deleted?
}

в этом примере деструктор будет вызываться, когда скрипт выходит из области MyPHPFunc, потому что $foo больше не будет доступна?

5 ответов


в PHP все значения сохраняются в так называемом zvals. Те zvals содержат фактические данные, введите информацию и-это важно для вашего вопроса-счетчик ссылок. Посмотрите на следующий фрагмент:

$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:

  • unseting 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 на refcounts обоих будет 1, но они все равно будут освобождены (и __destructed). В этом случае порядок уничтожения является неопределенным поведением.


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 вызывается успешно