Come distruggere un oggetto?


120

Per quanto ne so (che è molto poco), ci sono due modi, dato:

$var = new object()

Poi:

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

Altro metodo migliore? Sto spaccando i capelli qui?

Risposte:


152

Stai cercando unset().

Ma tieni presente che non puoi distruggere esplicitamente un oggetto.

Rimarrà lì, tuttavia se disattivi l'oggetto e il tuo script spinge PHP ai limiti di memoria, gli oggetti non necessari verranno raccolti in modo spazzatura. Vorrei andare con unset()(invece di impostarlo su null) in quanto sembra avere prestazioni migliori (non testato ma documentato su uno dei commenti dal manuale ufficiale di PHP).

Detto questo, tieni presente che PHP distrugge sempre gli oggetti non appena viene pubblicata la pagina. Quindi questo dovrebbe essere necessario solo su loop molto lunghi e / o pagine ad alta intensità.


1
Quindi Frankie, vengo da C ++, dove quando usiamo newuna volta, dobbiamo usare deleteuna volta. Questo non è vero in PHP? C'è la garbage collection automatica quando l'oggetto non è più necessario?
gsamaras

3
@gsamaras è vero. Tuttavia, puoi anche avere perdite e dovresti leggere di più sul GC di php se stai facendo daemon o simili. Nella maggior parte dei siti la richiesta è così breve che non ha importanza. php.net/manual/en/features.gc.refcounting-basics.php
Frankie

Non unset()elimina il riferimento all'oggetto?
Yousha Aleayoub

9

Un post utile che spiega diversi malintesi su questo:

Non chiamare esplicitamente il distruttore

Questo copre diverse idee sbagliate su come funziona il distruttore. Chiamarlo esplicitamente non distruggerà effettivamente la tua variabile, secondo il documento PHP5:

PHP 5 introduce un concetto di distruttore simile a quello di altri linguaggi orientati agli oggetti, come C ++. Il metodo distruttore verrà chiamato non appena non ci sono altri riferimenti a un particolare oggetto, o in qualsiasi ordine durante la sequenza di spegnimento.

Il post sopra afferma che l'impostazione della variabile su null può funzionare in alcuni casi, purché nient'altro punti alla memoria allocata.


2

Risposta breve: sono necessari entrambi.

Penso che sia stata data la risposta giusta, ma in minima parte. Sì, generalmente unset () è il migliore per "velocità", ma se vuoi recuperare immediatamente la memoria (al costo della CPU) dovresti usare null.

Come altri menzionati, l'impostazione su null non significa che tutto sia stato recuperato, puoi avere oggetti di memoria condivisa (non clonati) che impediranno la distruzione dell'oggetto. Inoltre, come altri hanno detto, non puoi comunque "distruggere" gli oggetti esplicitamente, quindi non dovresti provare a farlo comunque.

Dovrai capire qual è il migliore per te. Inoltre puoi usare __destruct () per un oggetto che verrà chiamato su unset o null ma dovrebbe essere usato con attenzione e come altri hanno detto, non essere mai chiamato direttamente!

vedere:

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

Qual è la differenza tra l'assegnazione di NULL e unset?


0

Questa è una semplice prova che non puoi distruggere un oggetto, puoi solo distruggere un collegamento ad esso.

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

ritorna

2

Guardalo in azione qui: https://eval.in/1054130


3
Bene, hai distrutto $var2che era un riferimento $var. Ora distruggi anche tu $vare, presumendo che non ci siano altri riferimenti sull'oggetto, hai finito.
i336_

4
Non stai distruggendo un oggetto, stai distruggendo un puntatore all'oggetto. È una grande differenza.
Yevgeniy Afanasyev

1
In altre lingue puoi distruggere un oggetto e tutti gli altri puntatori ti daranno eccezioni o spazzatura, ma non è un caso per php
Yevgeniy Afanasyev

1
Non puoi distruggere. Se non è presente alcun riferimento che contiene l'oggetto, l'oggetto è pronto per essere raccolto dal Garbage Collector. E non puoi forzare l'esecuzione del garbage collector.
Daniel

0

Potrebbe trovarsi in una situazione in cui stai creando un nuovo oggetto mysqli.

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

ma anche dopo aver chiuso l'oggetto

$MyConnection->close();

se utilizzerai print_r()per controllare il contenuto di $MyConnection, otterrai un errore come di seguito:

Error:
mysqli Object

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

in tal caso non è possibile utilizzarlo unlink()perché unlink()richiederà una stringa del nome del percorso ma in questo caso $MyConnectionè un oggetto.

Quindi hai un'altra scelta di impostare il suo valore su null:

$MyConnection = null;

ora le cose vanno bene, come ti aspettavi. Non hai alcun contenuto all'interno della variabile$MyConnection e hai già ripulito l'oggetto mysqli.

È consigliabile chiudere l'oggetto prima di impostare il valore della variabile su null.


-7

Vorrei andare con unset perché potrebbe dare al garbage collector un suggerimento migliore in modo che la memoria possa essere nuovamente disponibile prima. Fai attenzione che qualsiasi cosa a cui l'oggetto punta abbia altri riferimenti o venga prima disattivata o dovrai davvero aspettare il garbage collector poiché non ci sarebbero quindi handle per loro.


16
A meno che tu non abbia effettivamente delle fonti per eseguire il backup delle tue risposte, probabilmente non dovresti pubblicare ciò che pensi "potrebbe" accadere. Non è utile e porta a questo tipo di disinformazione presa come verità e ripetuta.
meagar

1
@meagar che è il motivo esatto per cui mi sono collegato alla pagina del manuale ufficiale dove, nei commenti, c'è un esempio di test che confronta unset () con null.
Frankie
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.