Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Why is an empty foreach loop can change the result.

I have the following code:

$variable = [1,2,3,4];
foreach ($variable  as $key => &$value) 
  $value ++;

var_dump($variable);

The result I get is:

array (size=4)
  0 => int 2
  1 => int 3
  2 => int 4
  3 => &int 5

Now, when I add an empty foreach loop like this:

$variable  = [1,2,3,4];
foreach ($variable  as $key => &$value) 
  $value ++;

foreach ($variable  as $key => $value);

var_dump($variable);

I get this :

array (size=4)
  0 => int 2
  1 => int 3
  2 => int 4
  3 => &int 4

can someone explain me why the last element doesn't change when I add the second empty loop, and why there is a & infront of the last element?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
196 views
Welcome To Ask or Share your Answers For Others

1 Answer

At the end of the first loop, $value is pointing to the same place as $variable[3] (they are pointing to the same location in memory):

$variable  = [1,2,3,4];
foreach ($variable  as $key => &$value) 
    $value ++;

Even as this loop is finished, $value is still a reference that's pointing to the same location in memory as $variable[3], so each time you store a value in $value, this also overwrites the value stored for $variable[3]:

foreach ($variable as $key => $value);
var_dump($variable);

With each evaluation of this foreach, both $value and $variable[3] are becoming equal to the value of the iterable item in $variable.

So in the 3rd iteration of the second loop, $value and $variable[3] become equal to 4 by reference, then during the 4th and final iteration of the second loop, nothing changes because you're passing the value of $variable[3] (which is still &$value) to $value (which is still &$value).

It's very confusing, but it's not even slightly idiosyncratic; it's the code executing exactly as it should.

More info here: PHP: Passing by Reference


To prevent this behavior it is sufficient to add an unset($value); statement after each loop where it is used. An alternative to the unset may be to enclose the foreach loop in a self calling closure, in order to force $value to be local, but the amount of additional characters needed to do that is bigger than just unsetting it:

(function($variable){
   foreach ($variable  as $key => &$value) $value++;
})($variable);


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...