2011-03-29 11 views
34

En C++, si pasa una matriz grande a una función, debe pasarla por referencia, para que no se copie a la nueva función que desperdicia memoria. Si no lo quiere modificado, páselo por referencia.¿Cuándo es bueno usar pasar por referencia en PHP?

¿Alguien puede verificar que pasar por referencia también me ahorrará memoria en PHP? Sé que PHP no usa direcciones para referencias como C++, es por eso que estoy un poco incierto. Esa es la pregunta.

+1

Solo una nota relacionada con C++: Las matrices pasadas a funciones son en realidad punteros, por lo que pasan una referencia para ellos es innecesario y en realidad no hace lo que crees que hace. Totalmente de acuerdo en la const embargo! – Aaron

Respuesta

52

La siguiente no se aplica a objetos, como ya se ha indicado aquí. Pasar matrices y valores escalares por referencia solo le ahorrará memoria si planea modificar el valor aprobado, ya que PHP utiliza una política de copia sobre cambio (también conocida como copiar con escritura). Por ejemplo:

# $array will not be copied, because it is not modified. 
function foo($array) { 
    echo $array[0]; 
} 

# $array will be copied, because it is modified. 
function bar($array) { 
    $array[0] += 1; 
    echo $array[0] + $array[1]; 
} 

# This is how bar shoudl've been implemented in the first place. 
function baz($array) { 
    $temp = $array[0] + 1; 
    echo $temp + $array[1]; 
} 


# This would also work (passing the array by reference), but has a serious 
#side-effect which you may not want, but $array is not copied here. 
function foobar(&$array) { 
    $array[0] += 1; 
    echo $array[0] + $array[1]; 
} 

En resumen:

  • Si está trabajando en un arsenal muy grande y el plan de modificarlo dentro de una función, en realidad se debe utilizar una referencia a evitar que se copian , que puede disminuir seriamente el rendimiento o incluso agotar el límite de memoria.

  • Si es evitable (es decir, arreglos pequeños o valores escalares), siempre usaría un enfoque de estilo funcional sin efectos secundarios, porque tan pronto como pasa algo por referencia, nunca puede estar seguro qué variable pasada puede contenerse después de la llamada a la función, lo que a veces puede llevar a errores desagradables y difíciles de encontrar.

  • Los valores escalares en mi humilde opinión nunca se deben pasar por referencia, ya que el impacto en el rendimiento no puede ser tan grande como para justificar la pérdida de transparencia en el código.

+0

Gracias y +1 para la explicación. Como tuve dificultades para encontrar información en copy-on-change: mira (google) para "copiar al escribir" y llegarás a http://php.net/manual/en/internals2.variables.intro.php – dennis

8

En PHP:

  • objetos se pasan por referencia - siempre
  • matrices y escalares se pasan por valor por defecto; y se puede pasar by reference, usando un & en la declaración de la función.


Para la parte de rendimiento de su pregunta, PHP no se ocupa de que de la misma manera como C/C++; usted debe leer el siguiente artículo: Do not use PHP references


1. O eso es lo que se suele decir - incluso si no es "del todo cierto" - ve Objects and references

+0

Estoy un poco confundido ... ¿significa esto que podría crear una clase singleton y pasar una referencia a cada visitante de un sitio, en lugar de consultar la base de datos para cada uno de ellos? (todos los visitantes solicitan los mismos datos) – sdadffdfd

+3

En PHP, no tendrá un Singleton "por servidor", sino un singleton "por ejecución de un script". Cada usuario tendrá su ejecución distinta e independiente del script, lo que significa que cada uno tendrá su propio espacio de memoria; su singleton será un singleton para una ejecución del script; y cada ejecución del script tendrá su propia instancia de singleton. –

+0

eso es triste ... sería genial tener esa función en php. Gracias. – sdadffdfd

8

La respuesta corta es referencias de uso cuando se necesita la funcionalidad que proporcionan. No pienses en ellos en términos de uso de memoria o velocidad. Pasar por referencia siempre será más lento si la variable es de solo lectura.

Todo se pasa por valor, incluidos los objetos. Sin embargo, es el identificador del objeto que se pasa, por lo que a menudo las personas lo llaman por referencia erróneamente porque se ve así.

Entonces, ¿qué funcionalidad proporciona? Se le da la capacidad de modificar la variable en el ámbito global del script:

class Bar {} 
$bar = new Bar(); 

function by_val($o) { $o = null; } 
function by_ref(&$o) { $o = null; } 

by_val($bar); // $bar is still non null 
by_ref($bar); // $bar is now null 

Así que si usted necesita tal funcionalidad (lo más a menudo no lo hace), a continuación, utilizar una referencia. De lo contrario, solo pasa por valor.

funciones que se ven así:

$foo = modify_me($foo); 

veces son buenos candidatos para el paso por referencia, pero debe quedar absolutamente claro que la función modifica la aprobada en variable. (Y si tal función es útil, a menudo es porque realmente debería ser parte de una clase que modifica sus propios datos privados).

Cuestiones relacionadas