Por que o PHP substitui os valores quando eu itera através dessa matriz duas vezes (por referência, por valor)

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

  •  27-09-2019
  •  | 
  •  

Pergunta

Se eu iterar através de uma matriz duas vezes, uma vez por referência e, em seguida, por valor, o PHP substituirá o último valor na matriz se eu usar o mesmo nome de variável para cada loop. Isso é melhor ilustrado por meio de um exemplo:

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

Resultado:

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

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

Observe que não estou procurando uma correção, estou procurando entender por que isso está acontecendo. Observe também que isso não acontece se os nomes da variável em cada loop não forem chamados $element, então acho que isso tem a ver com $element ainda estar no escopo e uma referência após o final do primeiro loop.

Foi útil?

Solução

Após o primeiro elemento do loop, o elemento ainda é uma referência ao último elemento/valor da matriz $.
Você pode ver isso quando usa var_dump () em vez de print_r ()

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

Observe isso e em &int(2).
Com o segundo loop, você atribui valores ao $ elemento. E como ainda é uma referência, o valor na matriz também é alterado. Experimente com

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

como o segundo loop e você verá.
Portanto, é mais ou menos o mesmo que

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

(apenas com loops e multiplicação ... ei, eu disse "mais ou menos" ;-))

Outras dicas

Aqui está uma explicação do próprio homem:

$y = "some test";

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

Aqui $y é uma entrada de tabela de símbolos referenciando uma string contendo "algum teste". Na primeira iteração que você essencialmente faz:

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

Então agora o armazenamento associado a $yé substituído pelo valor de $myarray. Se $y está associado a algum outro armazenamento por meio de uma referência, que o armazenamento será alterado.

Agora digamos que você faça isso:

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

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

Aqui $y está associado ao mesmo armazenamento que $a Através de uma referência, então quando a primeira iteração faz:

$y = $myarray[0];

O único lugar que a string de "teste" pode ir é no armazenamento associado a $y.

É assim que você corrigeria esse 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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top