¿Por qué PHP sobrescribe los valores cuando itero a través de esta matriz dos veces (por referencia, por valor)

StackOverflow https://stackoverflow.com/questions/2645499

  •  27-09-2019
  •  | 
  •  

Pregunta

Si itero a través de una matriz dos veces, una vez por referencia y luego por valor, PHP sobrescribirá el último valor en la matriz si uso el mismo nombre de variable para cada bucle. Esto se ilustra mejor a través de un ejemplo:

$array = range(1,5);
foreach($array as &$element)
{
  $element *= 2;
}
print_r($array);
foreach($array as $element) { }
print_r($array);

Producción:

Array ([0] => 2 [1] => 4 [2] => 6 [3] => 8 [4] => 10 )

Array ([0] => 2 [1] => 4 [2] => 6 [3] => 8 [4] => 8 )

Tenga en cuenta que no estoy buscando una solución, estoy buscando entender por qué está sucediendo esto. También tenga en cuenta que no sucede si los nombres variables en cada bucle no se llaman cada uno $element, así que supongo que tiene que ver con $element todavía está en alcance y una referencia después del final del primer bucle.

¿Fue útil?

Solución

Después del primer bucle $, el elemento sigue siendo una referencia al último elemento/valor de $ array.
Puede ver que cuando usa var_dump () en lugar de print_r ()

array(5) {
  [0]=>
  int(2)
...
  [4]=>
  &int(2)
}

Tenga en cuenta que y en &int(2).
Con el segundo bucle asigna valores a $ elemento. Y dado que todavía es una referencia, el valor en la matriz también cambia. Pruébalo con

foreach($array as $element)
{
  var_dump($array);
}

Como el segundo bucle y verás.
Entonces es más o menos lo mismo que

$array = range(1,5);
$element = &$array[4];
$element = $array[3];
// and $element = $array[4];
echo $array[4];

(solo con bucles y multiplicación ... oye, dije "más o menos" ;-))

Otros consejos

Aquí es una explicación del hombre mismo:

$y = "some test";

foreach ($myarray as $y) {
    print "$y\n";
}

Aquí $y es una entrada de tabla de símbolos que hace referencia a una cadena que contiene "alguna prueba". En la primera iteración que esencialmente lo haces:

$y = $myarray[0];  // Not necessarily 0, just the 1st element

Así que ahora el almacenamiento asociado con $yse sobrescribe por el valor de $myarray. Si $y está asociado con algún otro almacenamiento a través de una referencia, ese almacenamiento se cambiará.

Ahora digamos que haces esto:

$myarray = array("Test");
$a = "A string";
$y = &$a;

foreach ($myarray as $y) {
    print "$y\n";
}

Aquí $y está asociado con el mismo almacenamiento que $a a través de una referencia, así que cuando la primera iteración lo hace:

$y = $myarray[0];

El único lugar donde la cadena de "prueba" puede ir es al almacenamiento asociado con $y.

Así es como solucionaría este problema:

foreach($array as &$element)
{
    $element *= 2;
}
unset($element); #gets rid of the reference and cleans the var for re-use.

foreach($array as $element) { }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top