Perché i riferimenti vengono usati raramente in PHP?


26

Ho una certa conoscenza del C ++ e so che i puntatori sono comunemente usati lì, ma ho iniziato a guardare il codice open source PHP e non vedo mai il codice usando i riferimenti nei metodi.

Al contrario, il codice utilizza sempre un valore restituito anziché passare il riferimento alla variabile al metodo, che quindi modifica il valore di quella variabile e lo restituisce.

Ho letto che l'uso dei riferimenti utilizza meno memoria, quindi perché non vengono utilizzati in PHP?


19
L'uso dei parametri pass-by-reference è una "programmazione di effetti collaterali": l'utilizzo di una funzione per restituire un singolo valore è significativamente più chiaro durante la lettura del codice. Detto questo, alcune funzioni principali di PHP usano riferimenti.
Halfer

3
PHP passa gli oggetti per riferimento per impostazione predefinita.

2
i tipi di array sono un esempio eccellente delle funzioni principali di PHP che passano per riferimento
Mark Baker,

2
I riferimenti PHP non sono puntatori e spesso sono un dolore nel culo se non li aspetti completamente dove appaiono.
lanzz,

2
Se hai bisogno di più resi, return array($foo, $bar);elist($A, $B) = foobar();
Izkata,

Risposte:


49

La tua affermazione che i riferimenti sono usati raramente non è corretta. Come altri hanno già accennato, ci sono molte funzioni native che usano riferimenti, esempi notevoli includono le funzioni di ordinamento degli array e preg_match()/ preg_match_all(). Se si utilizza una di queste funzioni nel codice, si utilizzano anche riferimenti.

Passando, i riferimenti in PHP non sono puntatori. Dal momento che provieni da uno sfondo C ++ posso capire la confusione, ma i riferimenti PHP sono una bestia completamente diversa, sono alias di una tabella di simboli . Qualsiasi miglioramento delle prestazioni che potresti aspettarti dai riferimenti C ++ semplicemente non si applica ai riferimenti PHP.

In effetti, nella maggior parte degli scenari il passaggio per valore è più veloce e richiede meno memoria rispetto al passaggio per riferimento. Zend Engine, il core di PHP, utilizza un meccanismo di ottimizzazione copia su scrittura che non crea una copia di una variabile fino a quando non viene modificata. Il passaggio per riferimento di solito interrompe il modello di copia su scrittura e richiede una copia sia che si modifichi il valore o meno.

Non aver paura di usare i riferimenti in PHP quando è necessario, ma non limitarti a fare un tentativo di micro-ottimizzazione. Ricorda, l'ottimizzazione prematura è la radice di tutti i mali .

Ulteriori letture:


Grazie per la correzione @NikiC. Un po 'pigro rispondi a questo ...
yannis

Per completare la risposta, sarebbe utile sottolineare che tutti gli oggetti vengono passati per riferimento in PHP.
Florian Margaine

@FlorianMargaine Questo non è del tutto esatto (vedi il secondo link in ulteriori letture).
yannis

2
@FlorianMargaine No, i due sono molto diversi ed è importante rendersi conto del perché.
phant0m

3
@FlorianMargaine No, supponiamo che gli oggetti siano stati passati per riferimento in PHP: f($obj)dato function f($x) { $x = new X; }, avrebbe fatto $objriferimento a un oggetto diverso rispetto a prima della chiamata a f(). Tuttavia, poiché gli oggetti non vengono passati per riferimento, $ obj non viene modificato se si dovesse eseguire questo con PHP. In questo modo, PHP fa lo stesso di Java.
phant0m

8

PHP fa già una cosa di copia su scrittura in cui non crea un nuovo valore finché non si cambia qualcosa, quindi non c'è molta memoria salvata utilizzando i riferimenti. Farlo può anche rovinare alcune cose che PHP fa internamente per ridurre l'utilizzo della memoria, peggiorando le cose.

Aggiungete a ciò il fatto che i riferimenti rendono le cose un po 'troppo magiche in generale. L'impostazione predefinita, e quindi ciò che la maggior parte della gente si aspetta, è pass-by-value; quando passo $ia una funzione, complica enormemente le cose a cui preoccuparsi se quella funzione si trasforma misteriosamente $iin qualcos'altro, e quindi crea copie difensive nel caso. (Può già modificare $ise il valore è un oggetto, ma secondo me non dovrebbe.)

Fondamentalmente, troverei utile solo il riferimento pass-by per i parametri "out", ovvero le variabili che mi aspetto di recuperare dalla funzione piuttosto che passare, a la preg_match's &$matches. Anche per le funzioni che modificano chiaramente l'oggetto che viene passato, come sorto array_pop, sembra un po 'icky ... ma questo è ciò in cui siamo bloccati.


5

PHP è un linguaggio orientato al web.
Le pagine Web vengono pubblicate rapidamente e devono essere leggere.
Il normale programma PHP vive una frazione di secondo e consuma poche centinaia di kilobyte di memoria.
Non è utile per tali ottimizzazioni.


1
Questo. Non ha bisogno di puntatori / riferimenti, in quanto non si scherza su un livello così basso come C ++.
Kenneth Worden,

8
Perché questo post ottiene 5+ ??? Fa a) non rispondere alla domanda b) non è corretto

1
Quindi i riferimenti sono lenti e consumano troppa memoria?
Rocket Hazmat,

1
@RocketHazmat Sì, stranamente è vero.
yannis,

3

Alcuni motivi al volo:

  • PHP è un linguaggio di scripting e non mira a essere utilizzato come software incorporato di base (in sostanza, la memoria viene cancellata alla fine dello script),
  • Dal momento che PHP5, il pass-by-reference è implicito per i parametri degli oggetti (quindi PHP usa il pass-by-reference "nella tua schiena").

1
Vedi: php.net/manual/en/language.oop5.references.php per il tuo secondo punto.
yannis,

2

Penso che questa sia solo una scelta degli sviluppatori, niente a che fare con la lingua. Un sacco di codice PHP (integrato e non) usa riferimenti. Dai un'occhiata alle funzioni dell'array in PHP, molte di queste usano riferimenti. preg_matchusa riferimenti.

Penso che uno dei motivi per cui gli sviluppatori scelgono di non usare i riferimenti è perché può essere fonte di confusione. Chiamate una funzione e una delle variabili può (o non può) essere aggiornata perché era un riferimento. Quindi, quando esegui il debug, potrebbe non essere chiaro perché il valore di $xjsut sia cambiato magicamente.


1

Il problema fondamentale con la tua domanda è che supponi che questo sia comune anche in C ++. Non lo è. Non ci piacciono i parametri di output e li usiamo il meno possibile, sono solo molto comuni nelle API in stile C.


0

Conosco molte funzioni php che lo fanno. Dai un'occhiata ad preg_match()esempio. $matchessarà passato per riferimento

Se si desidera scrivere una funzione per sé che accetta argomenti per riferimento, utilizzare la sintassi seguente

function byref(&$a, &$b, $c) {
    $a += $c;
    $b += $c;
    return $a * $b;
}

$ a e $ b vengono passati per riferimento $ c viene passato per valore.

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.