The problem

To raise questions, let’s look at the following code:

<? php $arr = [ 'a', 'b', 'c', 'd', ]; foreach ($arr as &$each){ echo $each; } echo PHP_EOL; foreach ($arr as $each){ echo $each; }Copy the code

So this code is very simple, it prints the elements of the array twice, and it feels like it prints abcd twice, right? Sorry, the output is as follows:

Does it feel weird? I didn’t assign to the array. Why did the last element of the array change the second time through the loop?

Problem analysis

Take a look at the following modified code:

<? php $arr = [ 'a', 'b', 'c', 'd', ]; foreach ($arr as &$each){ echo $each; } echo PHP_EOL; $each = '1'; var_dump($arr);Copy the code

Did you find something?

Modifying each modifies the last element of arR. Why?

Those of you who have experience with C probably know what’s going on.

If you look closely at the foreach loop above, the each variable uses the ampersand symbol, which is the equivalent of addressing in C

PHP’s Foreach will assign the current element to each at each loop and then enter the body of the loop

When foreach is done, the each variable is not freed but refers to the last element in the ARR array, so when each is assigned later, it actually changes to the last element of the ARR array

Now that the process is clear, let’s undo the first two foreach processes:


After the first foreach completes, it is clear that each refers to the last element of the array, so let’s go to the second foreach:

  • First traversal, arr [0] assigned to each, the equivalent of arr [3] = arr [0], the arr is: [‘ a ‘, ‘b’, ‘c’, ‘a’]
  • A second time will traverse, arr [1] assigned to each, the equivalent of arr [3] = arr [1], the arr is: [‘ a ‘, ‘b’, ‘c’, ‘b’]
  • Third traversal, arr [2] assigned to each, the equivalent of arr [3] = arr [2], the arr is: [‘ a ‘, ‘b’, ‘c’, ‘c’]
  • Fourth traversal, arr [3] assigned to each, the equivalent of arr [3] = arr [3], the arr is: [‘ a ‘, ‘b’, ‘c’, ‘c’]

The analysis result is the same as the previous output result, we will print out each change of the second foreach, the code is as follows:

<? php $arr = [ 'a', 'b', 'c', 'd', ]; foreach ($arr as &$each){ } foreach ($arr as $each){ var_dump($arr); }Copy the code

The screenshot is as follows:

The results are in complete agreement with our analysis

I use PHP version 7.2