Home  >  Article  >  Backend Development  >  Detailed explanation of using PHP reference types with caution_PHP Tutorial

Detailed explanation of using PHP reference types with caution_PHP Tutorial

WBOY
WBOYOriginal
2016-07-13 17:00:10894browse

Use PHP references with caution Reference types (Reference) 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 as long as we trace the definition of the variable, we 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.

The code is as follows Copy code
 代码如下 复制代码

$x = 21;
$y = 7;

$z = &$x;
$z = &$y;

$x = 21;

$y = 7;

 代码如下 复制代码

int(21)
int(7)
int(7)从结果上看出,$x保持不变,只是$z被改变成了对$y的引用。相当于先unset了$z变量然后赋予了新值。

$z = &$x;
unset($z);
$z = &$y;这其实是比较合理逻辑,就比如下边的代码,我们并不是得到类似于“指向指针的指针(Pointer point to a Pointer)”那样的“引用引用的引用(Reference refer to a Referenece)”,只是多个引用到同一块内容的引用变量。

$x = 21;
$y = &$x;
$z = &$y

$z = &$x; $z = &$y;
var_dump($x,$y,$z); At first glance, it seems that $z becomes a reference to $x, and then the content of $z becomes a reference to $y. That is to say, both $x and $z are references to $y. But the actual output is:
The code is as follows Copy code
int(21) int(7) Int(7) It can be seen from the result that $x remains unchanged, but $z is changed into a reference to $y. It is equivalent to unsetting the $z variable first and then assigning a new value. $z = &$x; unset($z); $z = &$y; This is actually more reasonable logic. For example, in the code below, we do not get a "Reference refer to" similar to "Pointer point to a Pointer". a Reference)" are just multiple reference variables that refer to the same piece of content. $x = 21; $y = &$x; $z = &$y

Referencing an array element will make the element a reference type
Retrieving a reference from a variable will not change the type of the original variable, but if it is an element in an array, it will also change the element to a reference type.

Before looking at the problem code, the first thing to point out is:

Array assignment always involves value copying. Use the reference operator to copy an array by reference.

That is to say, PHP's array assignment is a copy rather than a reference. The assignment process will create a new array and assign it to the assigned variable. Array operations on the new variable will not affect the contents of the original array variable.

The code is as follows Copy code
 代码如下 复制代码


$a = array(21, 7);
$b = $a;
$b[0] = 7;
var_dump($a);
echo '
';
var_dump($b);

//Output:
//array(2) { [0]=> int(21) [1]=> int(7) }
//array(2) { [0]=> int(7) [1]=> int(7) }下边我们再来看看如果引用数组中的元素,会有什么异常。


$a = array(21, 7);
$c = & $a[0];
$b = $a;
$b[0]= "21";
$b[1]= "7";

var_dump($a);
echo '
';
var_dump($b);
echo '
';
var_dump($c);
echo '
';

// Output:
// array(2) { [0]=> &string(2) "21" [1]=> int(7) }
// array(2) { [0]=> &string(2) "21" [1]=> string(1) "7" }
// string(2) "21"

$a = array(21, 7);

$b = $a;

$b[0] = 7;

var_dump($a);

echo '
';

var_dump($b);

//Output:

//array(2) { [0]=> int(21) [1]=> int(7) }

//array(2) { [0]=> int(7) [1]=> int(7) } Let's take a look at what exceptions will occur if we reference elements in the array.

 代码如下 复制代码

unset($b);
unset($c);
var_dump($a);
   
// Output:
//array(2) { [0]=> string(2) "21" [1]=> int(7) }

$a = array(21, 7); $c = & $a[0]; $b = $a; $b[0]= "21"; $b[1]= "7"; var_dump($a); echo '
'; var_dump($b); echo '
'; var_dump($c); echo '
'; // Output: // array(2) { [0]=> &string(2) "21" [1]=> int(7) } // array(2) { [0]=> &string(2) "21" [1]=> string(1) "7" } // string(2) "21"
$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 the reference operator. That is to say, the first element of the array has become a reference type. Therefore, when assigning a value, it 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.
The code is as follows Copy code
unset($b); unset($c); var_dump($a);   // Output: //array(2) { [0]=> string(2) "21" [1]=> int(7) }

Avoid using PHP 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 a 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 function execution and the return value is invalid.
The code is as follows
 代码如下 复制代码
foreach ($array_var as $key => $value)
    $array_var [$key] = $newValue;
Copy code

foreach ($array_var as $key => $value)

$array_var [$key] = $newValue;

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 reference variable immediately when it is no longer needed to switch the connection with the content. 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.

http://www.bkjia.com/PHPjc/631276.htmlwww.bkjia.comtrue
http: //www.bkjia.com/PHPjc/631276.htmlTechArticle
Use PHP’s References with Care Reference types (Reference) are used in many computer languages, and are used as a very Powerful and useful features exist. It has a pointer-like implementation...
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn