Деструктор выводится при компиляции в последнюю очередь

Почему деструктор выводится в последнюю очередь даже если мы напечатаем цифру 5 после последнего обращения к методу класса?


<?php

class MathComplex
{
    public $re, $im;
    public $k = 0;
    function __construct($re = 0, $im = 0)
    {
        $this->re = $re;
        $this->im = $im;
        echo " ABC ";
    }

    // почему при выключении функции ничего не поменялось?

    function add(MathComplex $y) // указываем объект то же самого класса в качестве параметра функции
    {
        $this->re += $y->re;
        $this->im += $y->im;
    }

    function __toString()
    {
        return "{$this->re},  {$this->im}";
    }
    function __destruct()
      {
        echo "B!";
        $a = 3;
        echo $a;
        $this->k += $this->k+1;
        echo "счетчик равен:", $this->k;
     }
}
// require_once "classes.php";
  echo " obj1 = new MathComplex(445,41) : " ,$obj1 = new MathComplex(445,41);
  echo "\n"; // ABC 445, 41
  echo " obj2 = new MathComplex(1,14) : " ,$obj2 = new MathComplex(1,14);
  echo "\n"; // ABC 1, 14
  $obj1->add($obj2);
  echo "add: ", $obj1; // 446, 55
  echo "\n";
  echo " obj1 : ",$obj1; // 446, 55
  echo "\n";
  echo "obj1 : ",$obj1; // 446, 55
  echo "\n";
  echo "obj1->im  obj1->re: ", $obj1->im," ", $obj1->re;  // 55 446
  echo "\n";
  //echo "  destruct() : ",$obj1->__destruct();
 echo "\n";
// после вызова всех методов деструктор гарантировано вызовет два раза "B!3счетчик равен:1" при счетчик $k также, равен "1";
  echo 5; // если мы напечатаем "5", то деструктор будет после этой цифры
  echo "\n";




vedro-compota's picture

деструктор вызывается когда все ссылки на объект потеряны.
а потому:

  1. Вы должны или явно "потерять" эти ссылки (напр. присвоив переменной, которая раньше указывала на объект null или какое-то другое значение)
  2. Или они будут "потеряны" в связи с завершение работы скрипта (что в вашем случае и происходит)

_____________
матфак вгу и остальная классика =)

vedro-compota's picture

чтобы вызвать деструктор сразу можно написать:

$obj1 = null;

или там:

$obj1 = 'lalala';

-- и то и другое приведет к потере ссылки на первоначальный объект (при условии, что на него не указывали другие переменные).
Тем не менее, вызов деструктора в любом случае определяется алгоритмом уборки мусора, и в какой-то реализации может проходить и не сразу - это надо отдельно уточнять по документации.
В вашем же примере память очищалась только после завершения скрипта, так как до этого ссылка obj1 продолжала указывать на объект - а потому и деструктор вызывался после всех явных действий, непосредственно написанных в скрипте.

_____________
матфак вгу и остальная классика =)

vedro-compota's picture

Деструктор выводится при компиляции

не выводится, а выполняется, не при компиляции, а при интерпретации

_____________
матфак вгу и остальная классика =)