Як знищити об’єкт?


120

Наскільки я знаю (що дуже мало), є два способи:

$var = new object()

Тоді:

// Method 1: Set to null
$var = null;
// Method 2: Unset 
unset($var); 

Інший кращий метод? Я тут розщеплюю волоски?

Відповіді:


152

Ви шукаєте unset().

Але врахуйте, що ви не можете явно знищити об'єкт.

Він залишиться там, однак якщо ви скасуєте об'єкт і ваш скрипт підштовхне PHP до межі пам'яті, об'єкти, не потрібні, збиратимуть сміття. Я б пішов unset()(на відміну від встановлення його на нуль), оскільки, схоже, має кращі показники роботи (не перевірений, але задокументований на одному з коментарів з офіційного посібника PHP).

Зважаючи на це, майте на увазі, що PHP завжди знищує об'єкти, як тільки сторінка розміщується. Отже, це потрібно лише на дійсно довгих петлях та / або важких інтенсивних сторінках.


1
Отже, Френкі, я родом із С ++, де коли ми використовуємо newодин раз, то ми мусимо використовувати deleteодин раз. Це не вірно в PHP? Є автоматичне вивезення сміття, коли об’єкт більше не потрібен?
gsamaras

3
@gsamaras це правда. Ви також можете мати витоки, і вам слід прочитати більше в GC php, якщо ви робите демони чи подібні. На більшості сайтів запит настільки короткий, що не має значення. php.net/manual/en/features.gc.refcounting-basics.php
Frankie

Чи unset()видаляє посилання на Об’єкт?
Yousha Aleayoub

9

Зручна публікація, що пояснює кілька помилок з цього приводу:

Не дзвоніть деструктору прямо

Це охоплює кілька помилок щодо того, як працює деструктор. Викликаючи це явно, фактично не знищить вашу змінну, відповідно до документа PHP5:

PHP 5 вводить концепцію деструктора, подібну до концепції інших об'єктно-орієнтованих мов, таких як C ++. Метод деструктора буде викликаний, як тільки не буде інших посилань на певний об'єкт або в будь-якому порядку під час послідовності відключення.

У публікації вище зазначено, що встановлення змінної на null може працювати в деяких випадках, якщо нічого іншого не вказує на виділену пам'ять.


2

Коротка відповідь: обоє потрібні.

Я відчуваю, що правильну відповідь дали, але мінімально. Так взагалі unset () найкраще підходить для "швидкості", але якщо ви хочете повернути пам'ять негайно (за рахунок процесора), ви повинні використовувати null.

Як і інші згадані, встановлення значення "null" не означає, що все відшкодовано, ви можете мати об'єкти спільної пам’яті (незакриті), що запобіжить руйнуванню об'єкта. Більше того, як і інші казали, ви ніяк не можете "знищити" об'єкти явно, тому не варто намагатися це робити.

Вам потрібно буде розібратися, що найкраще для вас. Також ви можете використовувати __destruct () для об'єкта, який буде викликаний unset або null, але його слід використовувати обережно і, як казали інші, ніколи не викликайте прямо!

побачити:

http://www.stoimen.com/blog/2011/11/14/php-dont-call-the-destructor-explicitly/

Яка різниця між призначенням NULL та unset?


0

Це простий доказ того, що ви не можете знищити об'єкт, ви можете знищити лише посилання на нього.

$var = (object)['a'=>1];
$var2 = $var;
$var2->a = 2;
unset($var2);
echo $var->a;

повертає

2

Побачити це в дії можна тут: https://eval.in/1054130


3
Правильно, ви знищили, на $var2що було посилання $var. Тепер ви також знищуєте $varі, вважаючи, що немає інших посилань на об'єкт, ви закінчили.
i336_

4
Ви не знищуєте об'єкт, ви знищуєте вказівник на об’єкт. Це велика різниця.
Євген Афанасьєв

1
Іншими мовами ви можете знищити об’єкт, і всі інші покажчики дадуть вам винятки або сміття, але це не стосується php
Євген Афанасьєв,

1
Ви не можете знищити. Якщо немає посилання на об'єкт, об'єкт готовий до збору сміття. І ви не можете змусити запустити сміттєзбірник.
Даніель

0

Може виникнути ситуація, коли ви створюєте новий об’єкт mysqli.

$MyConnection = new mysqli($hn, $un, $pw, $db);

але навіть після того, як ви закриєте об’єкт

$MyConnection->close();

якщо ви будете використовувати print_r()для перевірки вмісту $MyConnection, ви отримаєте помилку, як показано нижче:

Error:
mysqli Object

Warning: print_r(): Property access is not allowed yet in /path/to/program on line ..
( [affected_rows] => [client_info] => [client_version] =>.................)

в такому випадку ви не можете використовувати, unlink()тому що unlink()буде потрібна рядок імені шляху, але в цьому випадку $MyConnectionце Об'єкт.

Отже, у вас є інший вибір встановлення його значення на нульове значення:

$MyConnection = null;

тепер все піде так, як ви і очікували. У вас немає вмісту всередині змінної $MyConnection, а також ви вже очистили об’єкт mysqli.

Рекомендована практика закривати Об'єкт перед тим, як встановити значення змінної null.


-7

Я б пішов з невдачею, тому що це може дати сміттєзбірщику кращий натяк, щоб пам'ять була знову доступною. Будьте уважні, що будь-які речі, на які об'єкт вказує, або мають інші посилання, або спочатку скасуються, або вам дійсно доведеться чекати на сміттєзбірнику, оскільки тоді не буде ручок до них.


16
Якщо ви насправді не маєте джерел для резервного копіювання відповідей, ви, ймовірно, не повинні публікувати те, що, на вашу думку, може статися. Це не корисно і призводить до того, що така дезінформація сприймається як правда і повторюється.
meagar

1
@meagar - це саме причина, чому я перейшов на офіційну сторінку керівництва, де в коментарях є зразок тесту, який порівнює unset () з null.
Френкі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.