2012-02-24 12 views
6

Cuando ejecuto el código de golpe:¿Por qué una variable asignada por valor a un elemento de matriz (después de una asignación previa por referencia) cambia cuando se cambia el elemento de matriz?

$var[0] = 'a'; 
$tmp = $var; 
$var[0] = 'b'; 
var_dump($tmp); 

la salida es:

array(1) { [0]=> string(1) "a" } 

Cuando agrego una línea de la siguiente manera:

$var[0] = 'a'; 
$foo = & $var[0]; # added line 
$tmp = $var; 
$var[0] = 'b'; 
var_dump($tmp); 

la salida se convierte en:

array(1) { [0]=> &string(1) "b" } 

Si asigno una variable $foo por referencia al elemento de una matriz $var[0], ¿se supone que la variable $tmp asignada por valor a la matriz $var cambia de esa manera? ¿Por qué pasó esto?

+0

Tenga en cuenta que los diversos términos "pass-by- *" solo se aplican a los argumentos de la función.No hay ninguna variable que pase aquí, solo asignación. – outis

Respuesta

3

Descargo de responsabilidad: No he podido encontrar una referencia explícita para esto, por lo que principalmente infiero aquí.

Una referencia regular funciona a través de la tabla de símbolos. Al crear una variable y un valor, tanto se almacenan en la tabla de símbolos local de este modo:

$foo = "bar"; 

+--------+-------+ 
| symbol | value | 
+--------+-------+ 
| $foo | "bar" | 
+--------+-------+ 

Cuando se crea una referencia, esto simplemente añade otro símbolo para el mismo valor de la tabla:

$bar =& $foo; 

+------------+-------+ 
| symbol  | value | 
+------------+-------+ 
| $foo, $bar | "bar" | 
+------------+-------+ 

claves de matriz se almacenan de forma diferente sin embargo:

$var[0] = 'a'; 

+--------+-----------------+ 
| symbol | value   | 
+--------+-----------------+ 
| $var | array(0 => 'a') | 
+--------+-----------------+ 

Hay una entrada en la tabla de símbolos para $var, pero los valores dentro de la matriz no están referenciados individualmente en la tabla de símbolos. Lo deduzco debe estar sucediendo cuando se crea una referencia al valor 'a' (almacenado en $var[0]) es que el valor 'a' se separa de la matriz $var y $var[0] mismo se convierte en una referencia a la nueva ubicación del lugar donde se almacena 'a':

$foo =& $var[0]; 

+--------+------------------+ 
| symbol | value   | 
+--------+------------------+ 
| $var | array(0 => %REF) | 
| $foo | %REF    | 
| %REF | 'a'    | 
+--------+------------------+ 

Supongo que la implementación interna de la tabla de símbolos no permite crear referencias directas a las teclas de matriz, por lo tanto, esta es la única forma de crear una referencia a un elemento de matriz.

Así que cuando se copia $var a $tmp, la referencia se copia con él:

$tmp = $var; 

+--------+------------------+ 
| symbol | value   | 
+--------+------------------+ 
| $var | array(0 => %REF) | 
| $foo | %REF    | 
| %REF | 'a'    | 
| $tmp | array(0 => %REF) | 
+--------+------------------+ 

Luego, cuando se cambia el valor $var[0] se refiere a, cambia el valor de %REF, que tanto $tmp y $var se refieren a.

Como dije, esto puede o no ser una explicación precisa de lo que sucede internamente, pero ilustra el principio.

Cuestiones relacionadas