Intereting Posts
Получение всех изображений из URL-адреса PHP 5.5 short_open_tag = on Security Hole? Считать общее количество подмассивов с определенными значениями в PHP Преобразование числа в слова в индийском валютном формате с величиной паи SQLSTATE : Нарушение ограничения целостности: 1452 Невозможно добавить или обновить дочернюю строку: ограничение внешнего ключа не удалось – Laravel Медленный скрипт PHP – автоматическая отладка и диагностика? PDO Prepare Statenent возвращает только имена столбцов вместо значений Получить xpath из результата поиска определенного шаблона регулярного выражения в кучке xml-файлов Что такое пространства имен? Как подключить Jms из PHP? Секция переопределения в шаблоне лезвия ларавеля, бросающая неопределенные переменные ошибки Отчеты проверки PHP. Селектор CSS не используется. Он используется эхом повторением тега PHP PHP / Javascript / JQuery – кодировка base64 sha256 Разделить разделяемые запятыми имена с помощью PHP переменная pass между php и javascript без страницы загрузки

Php Destruct Called Twice

В приведенном ниже коде показано, что destruct () вызывается дважды. Я хотел бы знать, почему?

class A { function hi(){ echo 'hi'; } function __destruct(){ echo 'destroy'; } } class B{ public $this_ = ''; function __construct(){ $this->this_ = new A; } function __call($method, $params) { return call_user_func_array(array($this->this_, $method), $params); } } $b = new B; $b->__destruct(); 

вывод:

 destroydestroy 

РЕДАКТИРОВАТЬ

Правильно указаны как zneak, так и TomcatExodus. Если я просто:

 [..code..] $b = new B; $b->__destruct(); print 'end of script'; 

На выходе будет показано:

 destroyend of scriptdestroy 

Вызов destruct не уничтожает объект. Вы вызываете его с помощью __destruct() в первый раз, а затем, когда PHP-скрипт завершается, он снова вызывает его при очистке.

Если вы хотите уничтожить объект до завершения сценария, unset() . Вы должны увидеть только один вызов разрушения.


В частности, ваш класс B создает отдельный экземпляр класса A Так как B также маршрутизирует вызовы методов через __call() в объект A , поэтому __destruct() на B вызывает __destruct() на A ; B не имеет деструктора, определенного и передает вызов.

Поскольку B не имеет метода __call вместо него __destruct метод __call (вы можете проверить это, добавив что-то вроде echo "calling $method" вашему методу __call ), а затем он будет перенаправлен на ваш объект A

Однако вызов __destruct не уничтожает объект: он просто вызывает код очистки, который должен быть связан с его уничтожением. Поэтому, как только вы закончите свой сценарий, когда объект A фактически уничтожен, его метод __destruct вызывается снова.

Если вы хотите удалить свой объект B , используйте unset($b) .

Вызов destructor вручную – одна из худших идей , особенно при работе с кодом других. Объект имеет логику, которая начинается с construct , проходит через methods и заканчивается при destruct . При destruct объект может потребовать некоторой очистки, а variables могут быть аннулированы. Когда destruct вызывается внутренне, в результате unset($Object) объект больше не доступен. Когда вы делаете это вручную, объект все еще находится в пределах досягаемости, но не поддерживает внутреннюю переменную, если он выполняет некоторую очистку.

Теперь подумайте, как бы это было, если вы вызвали метод на объекте, который полагается на данные, которые вы ранее недействительны, после обращения к destruct вручную. Это нарушает всю логику! Поэтому всегда unset() и пусть PHP делает свое дело.

Ручное уничтожение (размещение delete :)) является удивительным на C ++, если вы знаете, что делаете, особенно в сочетании с размещением нового . Но вы должны охранять себя на протяжении всей реализации и убедиться, что на самом деле у вас есть данные при вызове метода. И вы должны охранять себя в разрушении, если вы управляете памятью вручную, а не удалять указатели TWICE и сбой в этом процессе.

Управление памятью настолько круто в C ++! Я ненавижу GC (сборщики мусора) 🙂

— RANT OVER —

Вы вызываете деструктор вручную; но это не означает, что вы удаляете объект. Вы просто вызываете метод, и этот метод аналогичен любому другому.

Вызов метода $b->__destruct() вызывает $b->__destruct() $b->this_ , потому что $b не имеет явного метода деструктора.

Когда сценарий завершается, Zend Engine вызывает все экземпляры объектов, их деструкторы, а затем выполняет рутинную очистку, которая включает вызов деструкторов содержащихся объектов, т. $b->this_ После уничтожения $b , $b->this_ должен быть очищен и, чтобы сделать что, Двигатель вызывает свой конструктор автоматически.

Обратите внимание, что второй вызов не связан с уничтожением $b а из-за разрушения экземпляра A

Нет никакого препятствия в уничтожении объекта вручную, и он освобождает его ресурсы (если только объект не используется совместно, а затем GC не уничтожит его, если на нем больше нет ссылок, в PHP нет слабых ссылок ).

Пример работы GC: http://codepad.org/7JDBoOKY

Объекты разрушаются до завершения кода. Если бы это было не так, то порядок вывода был бы инвертирован.