Jak zniszczyć przedmiot?

120

O ile wiem (a to bardzo mało), istnieją dwa sposoby:

$var = new object()

Następnie:

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

Inna lepsza metoda? Czy ja tu rozdzielam włosy?

PandemoniumSyndicate
źródło

Odpowiedzi:

152

Szukasz unset().

Ale weź pod uwagę, że nie możesz jawnie zniszczyć obiektu.

Pozostanie tam, jednak jeśli wyłączysz obiekt, a skrypt wypchnie PHP do limitu pamięci, niepotrzebne obiekty zostaną usunięte. Poszedłbym z unset()(w przeciwieństwie do ustawiania go na null), ponieważ wydaje się, że ma lepszą wydajność (nie testowany, ale udokumentowany w jednym z komentarzy w oficjalnej instrukcji PHP).

To powiedziawszy, należy pamiętać, że PHP zawsze niszczy obiekty, gdy tylko strona jest wyświetlana. Więc powinno to być potrzebne tylko w przypadku naprawdę długich pętli i / lub bardzo intensywnych stron.

Frankie
źródło
1
Więc Frankie, pochodzę z C ++, gdzie, kiedy używamy newraz, to musi wykorzystać deletetylko raz. To nie jest prawda w PHP? Czy istnieje automatyczne usuwanie elementów bezużytecznych, gdy obiekt nie jest już potrzebny?
gsamaras,
3
@gsamaras to prawda. Możesz jednak mieć również wycieki i powinieneś przeczytać więcej na temat GC php, jeśli robisz demony lub podobne. W większości witryn żądanie jest tak krótkotrwałe, że nie ma to znaczenia. php.net/manual/en/features.gc.refcounting-basics.php
Frankie
Czy unset()usuwa odniesienie do obiektu?
Yousha Aleayoub
9

Poręczny post wyjaśniający kilka nieporozumień na ten temat:

Nie wzywaj Destructora jawnie

Obejmuje to kilka nieporozumień dotyczących działania destruktora. Wyraźne wywołanie go nie zniszczy twojej zmiennej, zgodnie z dokumentacją PHP5:

PHP 5 wprowadza koncepcję destruktora podobną do koncepcji innych języków zorientowanych obiektowo, takich jak C ++. Metoda destruktora zostanie wywołana, gdy nie będzie żadnych innych odwołań do określonego obiektu lub w dowolnej kolejności podczas sekwencji zamykania.

Powyższy post stwierdza, że ​​ustawienie zmiennej na null może działać w niektórych przypadkach, o ile nic innego nie wskazuje na przydzieloną pamięć.

Sturrockad
źródło
2

Krótka odpowiedź: potrzebne są oba.

Wydaje mi się, że podano właściwą odpowiedź, ale minimalną. Tak, generalnie unset () jest najlepsze dla „szybkości”, ale jeśli chcesz natychmiast odzyskać pamięć (kosztem procesora), powinieneś użyć null.

Podobnie jak inni wspomnieli, ustawienie na null nie oznacza, że ​​wszystko jest odzyskane, możesz mieć obiekty pamięci współdzielonej (niesklonowane), które zapobiegną zniszczeniu obiektu. Co więcej, jak powiedzieli inni, i tak nie możesz „niszczyć” obiektów w sposób jawny, więc i tak nie powinieneś próbować tego robić.

Musisz dowiedzieć się, który z nich jest dla Ciebie najlepszy. Możesz także użyć __destruct () dla obiektu, który będzie wywoływany w stanie nieustawionym lub zerowym, ale powinien być używany ostrożnie i, jak powiedzieli inni, nigdy nie powinien być wywoływany bezpośrednio!

widzieć:

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

Jaka jest różnica między przypisywaniem wartości NULL i unset?

Mike Q
źródło
0

To prosty dowód na to, że nie możesz zniszczyć obiektu, możesz tylko zniszczyć łącze do niego.

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

zwroty

2

Zobacz to w akcji tutaj: https://eval.in/1054130

Yevgeniy Afanasyev
źródło
3
Racja, zniszczyłeś, do $var2czego było odniesienie $var. Teraz również niszczysz $vari zakładając, że na obiekcie nie ma innych odniesień, gotowe.
i336_
4
Nie niszczysz obiektu, niszczysz wskaźnik do obiektu. To duża różnica.
Yevgeniy Afanasyev
1
W innych językach możesz zniszczyć obiekt, a wszystkie inne wskazówki dadzą ci wyjątki lub bzdury, ale tak nie jest w przypadku php
Yevgeniy Afanasyev
1
Nie możesz zniszczyć. Jeśli nie ma odniesienia przechowującego obiekt, obiekt jest gotowy do zebrania przez moduł odśmiecania pamięci. I nie możesz zmusić do uruchomienia garbage collectora.
Daniel
0

Może być w sytuacji, gdy tworzysz nowy obiekt mysqli.

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

ale nawet po zamknięciu obiektu

$MyConnection->close();

jeśli użyjesz print_r()do sprawdzenia zawartości $MyConnection, pojawi się błąd jak poniżej:

Error:
mysqli Object

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

w takim przypadku nie możesz użyć, unlink()ponieważ unlink()będzie wymagać ciągu nazwy ścieżki, ale w tym przypadku $MyConnectionjest to Object.

Masz więc inny wybór ustawienia jego wartości na null:

$MyConnection = null;

teraz wszystko idzie dobrze, jak się spodziewałeś. Nie masz żadnej zawartości wewnątrz zmiennej, $MyConnectiona także wyczyściłeś obiekt mysqli.

Zalecaną praktyką jest zamykanie Object przed ustawieniem wartości zmiennej na null.

Subrat Kumar Palhar
źródło
-7

Poszedłbym bez ustawienia, ponieważ może to dać odśmiecaczowi lepszą wskazówkę, aby pamięć mogła być ponownie dostępna wcześniej. Uważaj, aby wszystko, co wskazuje obiekt, albo miało inne odwołania, albo zostało najpierw rozbrojone, albo naprawdę będziesz musiał poczekać na moduł odśmiecania pamięci, ponieważ wtedy nie będzie do nich dojść.

hackartist
źródło
16
Jeśli nie masz rzeczywiście źródeł do tworzenia kopii zapasowych swoich odpowiedzi, prawdopodobnie nie powinieneś publikować tego, co myślisz, że „może” się wydarzyć. Nie jest to przydatne i prowadzi do tego, że tego rodzaju dezinformacja jest traktowana jako prawda i powtarzana.
meagar
1
@meagar to jest dokładny powód, dla którego utworzyłem link do oficjalnej strony podręcznika, na której w komentarzach znajduje się przykładowy test porównujący unset () z null.
Frankie