I. Problems
Let's take a look at an example:
<? Php
$ Ar = array (1, 2, 3 );
Var_dump ($ ar );
Foreach ($ ar as & $ v ){}
Foreach ($ ar as $ v ){}
Var_dump ($ ar );
?>
Output:
Array (3 ){
[0] =>
Int (1)
[1] =>
Int (2)
[2] =>
Int (3)
}
Array (3 ){
[0] =>
Int (1)
[1] =>
Int (2)
[2] =>
& Int (2)
}
??? Why is the value of the last element of the array changed without assigning values?
I have discovered this problem for a long time. I thought it was a PHP bug at first, and I threw it away. It would be okay if I didn't use references in foreach, use foreach $ k => $ v and then $ ar [$ k] to change the original array, slightly reducing the efficiency.
Ii. Analysis
It took me some time today to read the articles in the reference. I understood a little bit. It turned out to be like this:
When the first foreach with reference is executed, $ v points to the storage space of $ ar [0] at the beginning, and 1 is stored in the space. When foreach ends, $ v points to the storage space of $ ar [2], where 3 is stored. Next we need to start executing the second foreach. Note that, unlike the first foreach, the second foreach does not use a reference. In this case, the value assignment method is used to assign the value of $ ar to $ v in sequence. When the first element is reached, $ ar [0] must be assigned to $ v. The problem is that, since the first foreach is just executed, $ v is not a new variable, but a reference that already exists pointing to $ ar [2]. As a result, when assigning values to $ v, $ ar [0] = 1 is written to the actual storage space of $ ar [2], which is equivalent to assigning values to $ ar [2. The result of the second foreach execution is that the last element of the array is changed to the value of the second to last element. See article 2 for details.
If this is an error, the cause of the error lies in the use of referenced variables. When a referenced variable points to another variable, changing the value of the referenced variable will certainly affect other variables it points. Everyone knows it, but in this foreach example, coincidentally, the same variable is used twice, the previous is the referenced identity, and the last is the normal variable identity, this produces unexpected results. PHP developers also believe that this situation is caused by language characteristics, rather than a bug. Indeed, if you want to fix this problem, one method is to perform special processing on foreach, and the other is to limit the scope of $ v in foreach, both of these methods are inconsistent with the current PHP language features and developers are reluctant to modify them, But Warning is still described in the official documentation.
Iii. Solution
Simple, but not perfect. After using the referenced foreach, unset $ v. The example at the beginning is changed:
<? Php
$ Ar = array (1, 2, 3 );
Var_dump ($ ar );
Foreach ($ ar as & $ v ){}
Unset ($ v );
Foreach ($ ar as $ v ){}
Var_dump ($ ar );
?>
Running result:
Array (3 ){
[0] =>
Int (1)
[1] =>
Int (2)
[2] =>
Int (3)
}
Array (3 ){
[0] =>
Int (1)
[1] =>
Int (2)
[2] =>
Int (3)
}
Reference
Bug #29992 foreach by reference before upts the array: https://bugs.php.net/bug.php? Id = 29992
References and foreach: http://schlueters.de/blog/archives/141-References-and-foreach.html