Pasar por valor y pasar por referencia son conceptos básicos pero muy importantes en cualquier entorno de programación. En este post nos centraremos en PHP, pero el significado es el mismo en cualquier otro lenguaje.

Valor y referencia

En PHP, la información se puede pasar a las funciones y métodos a través de la lista de argumentos definida para la función o método en cuestión. En el siguiente ejemplo, la función suma() acepta dos argumentos:

function suma($num1, $num2) {
    echo $num1 + $num2;
}

De forma predeterminada, PHP pasa la información a las funciones y métodos por valor. Esto quiere decir que PHP le da el valor a la función, y solo el valor, para que haga con él lo que quiera:

function sumar_uno($x) {
   $x++;
   echo $x;
}

$a = 2;

sumar_uno($a); // 3

echo $a; // 2

Las variables se pueden entender como tentáculos que sostienen valores o información en memoria. Cada tentáculo tiene una referencia que PHP utiliza para saber que información exactamente es la que tiene que manipular.

Al pasar por valor, el argumento de la función crea su propia referencia, su propio tentáculo con el valor pasado. Dentro y fuera de la función las referencias en memoria son diferentes.

Hay que tener claro que la referencia y el nombre de la variable no son lo mismo; por eso pueden existir variables con el mismo nombre en contextos diferentes, por ejemplo, dentro y fuera de la función se puede utilizar el mismo nombre de variable pero manteniendo cada una su propia referencia:

function sumar_uno($a) {
    $a++;
    echo $a;
}

$a = 2;
sumar_uno($a); // 3
echo $a; // 2

Pasar por referencia

Pasar por referencia significa que además de pasar el valor a la función, se pasa la referencia a la variable original. De este modo, si el valor cambia dentro de la función, también cambiará en la variable original.

Para indicar que el argumento de una función se pasa por referencia, se utiliza el símbolo & (ampersand, et) delante del argumento.

function sumar_uno(&$x) {
    $x++;
    echo $x;
}

$a = 2;

sumar_uno($a); // 3

// $a se pasó por referencia a suma_uno()
// El cambio dentro de la función
// se refleja en la referencia original
echo $a; // 3

Entender la diferencia entre pasar por valor y pasar por referencia es esencial para entender como se comporta cada lenguaje de programación.

Si PHP pasa por valor de forma predeterminada y para pasar por referencia hay que indicarlo, otros lenguajes, por el contrario, pasan por referencia de forma predeterminada, por ejemplo JavaScript, donde distintos scopes o contextos para variables se pueden definir con var, let y const.

Llamar por referencia

Antes se podía definir una función con argumentos pasados por valor y pasar por referencia en tiempo de ejecución o en tiempo de llamada. Por ejemplo:

// el argumento se pasa por valor
function sumar_uno($x) {
  $x++;
  echo $x;
}

$a = 2;

// Se pasa por referencia
// en tiempo de llamada
sumar_uno(&$a);

A partir de PHP 5.3.0 pasar por referencia en tiempo de llamada se marcó como obsoleto, ya solo se puede utilizar el signo de referencia & en la definición de la función y sus argumentos, de lo contrario aparecerá el error “call-time pass-by-reference” .

Por este motivo, es preferible utilizar la expresión “pasar por referencia” y no “llamar por referencia”, aunque ambas se refieren exactamente a lo mismo y es habitual que se utilicen de forma indistinta.

Devolver y asignar por referencia

También se puede devolver por referencia. Si se utiliza el símbolo & delante del nombre de una función o de un método, la variable que devuelva se devolverá por referencia.

function &sumar_uno() {
    return $x++;
}

A diferencia de lo que ocurría al pasar argumentos por referencia, para utilizar la devolución por referencia, también hay que utilizar la asignación por referencia:

function &sumar_uno() {
    static $x = 1;
    $x++;
    return $x;
}

// Asignación por referencia
$x = &sumar_uno();

echo $x; // 2

sumar_uno();
sumar_uno();

echo $x; // 4