¿Por qué las referencias rara vez se usan en PHP?

26

Tengo cierto conocimiento de C ++ y sé que los punteros se usan comúnmente allí, pero he comenzado a mirar el código fuente PHP y nunca veo código usando referencias en los métodos.

En cambio, el código siempre usa un valor de retorno en lugar de pasar la referencia a la variable al método, que luego cambia el valor de esa variable y simplemente lo devuelve.

He leído que usar referencias usa menos memoria, entonces ¿por qué no se usan en PHP?

Alexander Cogneau
fuente
19
El uso de parámetros de paso por referencia es "programación de efectos secundarios": el uso de una función para devolver un valor único es significativamente más claro al leer el código. Dicho esto, bastantes funciones centrales de PHP usan referencias.
halfer
3
PHP pasa objetos por referencia por defecto.
2
Los tipos de matriz son un excelente ejemplo de las funciones principales de PHP que pasan por referencia
Mark Baker
2
Las referencias de PHP no son punteros, y a menudo son un fastidio si no las espera completamente donde aparecen.
lanzz
2
Si necesita múltiples devoluciones, return array($foo, $bar);ylist($A, $B) = foobar();
Izkata

Respuestas:

49

Su afirmación de que las referencias rara vez se usan es incorrecta. Como otros ya han mencionado que hay un montón de funciones nativas que usan referencias, ejemplos notables incluyen las funciones de ordenación de matrices y preg_match()/ preg_match_all(). Si está utilizando alguna de estas funciones en su código, también está utilizando referencias.

Continuando, las referencias en PHP no son punteros. Dado que proviene de un entorno de C ++, puedo entender la confusión, pero las referencias de PHP son una bestia completamente diferente, son alias de una tabla de símbolos . Cualquier aumento de rendimiento que podría haber esperado de las referencias de C ++ simplemente no se aplica a las referencias de PHP.

De hecho, en la mayoría de los escenarios, pasar por valor es más rápido y requiere menos memoria que pasar por referencia. Zend Engine, el núcleo de PHP, utiliza un mecanismo de optimización de copia en escritura que no crea una copia de una variable hasta que se modifica. Pasar por referencia generalmente rompe el patrón de copia en escritura y requiere una copia, ya sea que modifique el valor o no.

No tenga miedo de usar referencias en PHP cuando lo necesite, pero no lo haga solo como un intento de micro-optimización. Recuerde, la optimización prematura es la raíz de todo mal .

Otras lecturas:

Yannis
fuente
Gracias por la corrección @NikiC. Un poco flojo responder esta ...
Yannis
Para completar la respuesta, sería bueno señalar que todos los objetos se pasan por referencia en PHP.
Florian Margaine
@FlorianMargaine Eso no es del todo exacto (ver segundo enlace en más información)
Yannis
2
@FlorianMargaine No, los dos son muy diferentes y es importante darse cuenta de por qué es así.
phant0m
3
@FlorianMargaine No, supongamos que los objetos se pasaron por referencia en PHP: f($obj)dado function f($x) { $x = new X; }, habría hecho $objreferencia a un objeto diferente al anterior a la llamada a f(). Sin embargo, dado que los objetos no se pasan por referencia, $ obj no se modifica si tuviera que ejecutar esto con PHP. De esa manera, PHP hace lo mismo que Java.
phant0m
8

PHP ya hace una copia en escritura donde no crea un nuevo valor hasta que cambie algo, por lo que no se guarda mucha memoria al usar referencias. Si lo hace, incluso puede meterse con algunas cosas que PHP hace internamente para reducir el uso de memoria, lo que empeora las cosas.

Agregue a eso el hecho de que las referencias hacen que las cosas sean demasiado mágicas en general. El valor predeterminado, y por lo tanto lo que la mayoría de la gente espera, es pasar por valor; cuando paso $ia una función, se complica enormemente tener que preocuparme si esa función cambia misteriosamente $ia otra completamente diferente y, por lo tanto, hacer copias defensivas por si acaso. (Ya puede modificar $isi el valor es un objeto, pero en mi opinión no debería).

Básicamente, solo encontraría que el paso por referencia es útil para los parámetros "out", es decir, las variables que espero recuperar de la función en lugar de pasar, a la preg_match's &$matches. Incluso para funciones que modifican claramente el objeto que se pasa, como sorto array_pop, eso se siente un poco asqueroso ... pero eso es con lo que estamos atrapados.

cHao
fuente
5

PHP es un lenguaje orientado a la web.
Las páginas web se sirven rápidamente y deben ser livianas.
El programa PHP habitual vive una fracción de segundo y consume unos cientos de kilobytes de memoria.
No hay uso para tales optimizaciones.

Su sentido común
fuente
1
Esta. No necesita punteros / referencias, ya que no está jugando en un nivel tan bajo como C ++.
Kenneth Worden
8
¿Por qué esta publicación obtiene 5+? Sí a) no responde la pregunta b) no es correcto
1
¿Entonces las referencias son lentas y consumen demasiada memoria?
Rocket Hazmat
1
@RocketHazmat Sí, curiosamente es cierto.
Yannis
3

Algunas razones sobre la marcha:

  • PHP es un lenguaje de secuencias de comandos y no pretende ser utilizado como un software central integrado (básicamente, la memoria se borra al final de la secuencia de comandos),
  • Desde PHP5, el paso por referencia está implícito para los parámetros del objeto (por lo que PHP usa el paso por referencia "en su espalda").
AlterPHP
fuente
1
Ver: php.net/manual/en/language.oop5.references.php para su segundo punto.
yannis
2

Creo que esto es solo una elección de los desarrolladores, nada que ver con el lenguaje. Un montón de código PHP (incorporado y no) usa referencias. Eche un vistazo a las funciones de matriz en PHP, muchas de ellas usan referencias. preg_matchutiliza referencias

Creo que una de las razones por las que los desarrolladores eligen no usar referencias es porque puede ser confuso. Llama a una función y una de las variables puede (o no) actualizarse porque era una referencia. Entonces, cuando depura, puede que no esté claro por qué el valor de $xjsut cambió mágicamente.

Cohete Hazmat
fuente
1

El problema fundamental con su pregunta es que asume que esto también es común en C ++. No lo es No nos gustan los parámetros de salida y los usamos lo menos posible, solo son muy comunes en las API de estilo C.

DeadMG
fuente
0

Conozco muchas funciones php que lo hacen. Echa un vistazo preg_match()por ejemplo. $matchesserá aprobado por referencia

Si desea escribir una función para usted que tome argumentos por referencia, use la siguiente sintaxis

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

$ a y $ b se pasan por referencia $ c se pasa por valor.

hek2mgl
fuente