Reference types are used in many computer languages and exist as a very powerful and practical feature. It has an implementation similar to a pointer, but behaves differently from a pointer. For example, C++ references can allow different variables to point to the same object, while maintaining the direct use of dot to obtain object members, without the cumbersome use of dereference operator (*) and Pointer to Member operator (->). In Java and C#, references are directly used as the main type, and developers try to avoid using pointers.
Reference types have also been introduced in PHP. In terms of object assignment and transfer, it can basically be regarded as the same reference transfer as Java/C# (see Objects and references for details). But at the same time, it supports obtaining a reference to the content through the reference operator (&) on the basic type. However, in actual use, PHP's reference type has many problems due to the entire PHP design structure, causing unexpected results in the program.
Reference variables can be assigned new references
In C++, a reference type variable can only be assigned a reference value when it is defined, so we As long as you trace the definition of the variable, you can know what the variable is operating on.
But PHP is different. The definition of variables is blurred in PHP, and variables can be used without defining them. So a variable can be assigned a reference value multiple times.
$b in the code is just a simple assignment, except that there is an extra reference to get the first element, but it should still copy a new array. But the result is a modification of $b, which also changes the first element of $a, while the second element has no effect.
We also see an unusual thing from the output, that is, the type of the first element of the array has an extra '&' symbol. And this is exactly the reference operator. That is to say, the first element of the array has become a reference type. Therefore, assignment is also a reference copy, not a value copy.
This problem is very strange, and it also caused a lot of unnecessary trouble during development. I originally thought that the copied array was not related to the original array, but because of this unexpected reference type, I was confused during the operation. The original array is affected.
I don’t know if this is a bug in PHP or if it is intentionally designed this way. I have been searching online for a long time but there is no relevant explanation for this convenience. Only Float Middle's "PHP: References To Array Elements Are Risky" and Symmetric Designs' "Problems w/accessing a PHP array by reference" talk about this, but No reason was given.
Later, I saw several related reports (Bug6417, Bug7412, Bug15025, Bug20993) in the PHP Bug Report. Some say this is a bug and has been fixed in later versions. I don't understand the specifics, I can only avoid using references on arrays.
The more interesting thing is that if you unset those references and leave only one, then the array elements will become normal types without references.
This is actually something to pay attention to mentioned in the PHP Array Manual. It most often occurs in foreach, where you hope to change the value of the far array through a reference (see this article).
In fact, I want to change the value of the array element by using foreach with references, mainly because PHP's array is an Associative Array. This kind of array has "indefinite length, the index can be discontinuous, and strings and integers can be used as indexes at the same time." So we cannot simply increment the integer index using a for loop.
Of course we can directly change the value of the array element through $key like the code below, but this may have certain efficiency issues.
Another common place for references is to pass parameters by reference in function calls. The main reason is to use this method to allow the function to return multiple return values. For example, we want to use a representation to indicate whether an error occurs during execution of the function and the return value is invalid.
But because PHP functions can return different types, there is no need to pass in reference parameters as representation. Even if you really need multiple return values, you can still return an "array with a string as the primary key" as a solution, but you may need to point out in the documentation that each element corresponds to that result.
A better way to operate it is to use unset on the variable immediately to switch the connection with the content whenever the referenced variable no longer needs to be used. And even if the variable is not a reference type, we confirm that it is no longer used , and there will be no problem calling unset on it. At least it is guaranteed that reassigning the variable later will not affect the previous result.