Reference of php (that is, adding an ampersand in front of variables, functions, objects, etc.)
Quotation in PHP means: different names access the same variable content.
It is different from pointers in C language. The pointer in C language stores the content of the variable and the address stored in the memory.
1. Variable reference
PHP’s references allow you to use two variables to point to the same content
$a = " ABC " ;
$b =& $a ;
echo $a ; // Output here: ABC
// Output here: ABC
$b = " EFG " ;
echo $a ; // The value of $a here becomes EFG, so EFG
is output
Echo $ b; // Output EFG
?>
2. Function reference transfer (call by address)
I won’t go into details about the call by address. The code will be given directly below
Function test( & $a )
{
$a = $a + 100 ;
}
$b = 1 ;
Echo $ b; // Output 1
Test($b); // What $b is passed to the function here is actually the memory address where the variable content of $b is located. By changing the value of $a in the function, the value of $b can be changed
echo "
" ;
Echo $ b; // Output 101
?>
It should be noted that if test(1); is used here, an error will occur. You have to think about the reason yourself.
Note:
Do not add the & symbol in front of $b in the above "test($b);", but in the function "call_user_func_array", if you want to refer to the parameters, you need the & symbol, as shown in the following code:
function a( & $b ){
$b ++ ;
}
$c = 0 ;
call_user_func_array ( ' a ' , array ( & $c ));
echo $c ;
//output 1
?>
3. Function reference returns
Look at the code first
function & test()
{
static $b = 0; // Declare a static variable
$b = $b + 1 ;
echo $b ;
Return $b ;
}
$a = test(); // This statement will output the value of $b as 1
$a = 5 ;
$a = test(); // This statement will output that the value of $b is 2
$a =& test(); // This statement will output the value of $b as 3
$a = 5 ;
$a = test(); // This statement will output that the value of $b is 6
?>
Explanation below:
In this way, $a=test(); actually does not get a reference return from the function. It is no different from an ordinary function call. As for the reason: This is the regulation of PHP
PHP stipulates that what is obtained through $a=&test(); is the reference return of the function
As for what is a reference return (the PHP manual says: Reference return is used when you want to use a function to find which variable the reference should be bound to.) This nonsense made me unable to understand it for a long time
Using the above example to explain it is
Calling a function using $a=test() only assigns the value of the function to $a, and any changes to $a will not affect $b
in the function.
When calling a function through $a=&test(), its function is to point the memory address of the $b variable in return $b and the memory address of the $a variable to the same place
That is to say, the effect is equivalent to this ($a=&$b;), so changing the value of $a also changes the value of $b, so after executing
$a=&test();
$a=5;
From now on, the value of $b becomes 5
Static variables are used here to let everyone understand the reference return of functions. In fact, the reference return of functions is mostly used in objects
Attached is an official PHP example:
This is the way how we use pointer to access variable inside the class .
class talker{
private $data = ' Hi ' ;
public function & get(){
Return $this -> data;
}
Public function out(){
echo $this -> data;
}
}
$aa = new talker();
$d = & $aa -> get();
$aa -> out();
$d = ' How ' ;
$aa -> out();
$d = ' Are ' ;
$aa -> out();
$d = ' You ' ;
$aa -> out();
?>
the output is " HiHowAreYou "
4. Object reference
class a{
var $abc = " ABC " ;
}
$b = new a;
$c = $b ;
echo $b -> abc; // ABC
is output here
echo $c -> abc; // ABC
is output here
$b -> abc = " DEF " ;
echo $c -> abc; // DEF
is output here
?>
The above code is the running effect in PHP5
In PHP5, object assignment is a reference process. In the above column, $b=new a; $c=$b; is actually equivalent to $b=new a; $c=&$b;
The default in PHP5 is to call objects by reference, but sometimes you may want to create a copy of the object and hope that changes to the original object will not affect the copy. For this purpose, PHP5 defines a special method called __clone .
As of PHP 5, new automatically returns a reference, so using =& here is obsolete and produces an E_STRICT level message.
In php4, object assignment is a copy process,
For example: $b=new a, where new a produces an anonymous a object instance, and $b at this time is a copy of this anonymous object. In the same way, $c=$b is also a copy of the content of $b. Therefore, in php4, in order to save memory space, $b=new a will generally be changed to the reference mode, that is, $b=& new a.
Here’s another official example:
In php5, you don’t need to add anything else to achieve the “object reference” function:
class foo{
protected $name ;
function __construct( $str ){
$ This -& gt; name = $ str;
}
function __toString(){
Return 'My name is "'. $ This -& gt; name. '" And I live in "'. __Class____. '". "N";
}
function setName( $str ){
$ This -& gt; name = $ str;
}
}
out out out out out out of out of over
function __construct( $f ){
$this -> foo = $f ;
}
function __toString(){
Return 'master:'. __Class_________________. '| Foo:'. $ This -& gt; foo.
}
function setFooName( $str ){
$this -> foo -> setName( $str );
}
}
class MasterTwo{
protected $foo ;
function __construct( $f ){
$this -> foo = $f ;
}
function __toString(){
return ' Master: ' . __CLASS__ . ' | foo: ' . $this -> foo . " n " ;
}
function setFooName( $str ){
$this -> foo -> setName( $str );
}
}
$bar = new foo( ' bar ' );
print ( " n " );
print ( " Only Created $bar and printing $barn " );
print ( $bar );
print ( " n " );
print ( " Now $baz is referenced to $bar and printing $bar and $bazn " );
$baz =& $bar ;
print ( $bar );
print ( " n " );
print ( " Now Creating MasterOne and Two and passing $bar to both constructorsn " );
$m1 = new MasterOne( $bar );
$m2 = new MasterTwo( $bar );
print ( $m1 );
print ( $m2 );
print ( " n " );
print ( " Now changing value of $bar and printing $bar and $bazn " );
$bar -> setName( ' baz ' );
print ( $bar );
print ( $baz );
print ( " n " );
print ( " Now printing again MasterOne and Twon " );
print ( $m1 );
print ( $m2 );
print ( " n " );
print ( " Now changing MasterTwo's foo name and printing again MasterOne and Twon " );
$m2 -> setFooName( ' MasterTwo's Foo ' );
print ( $m1 );
print ( $m2 );
print ( " Also printing $bar and $bazn " );
print ( $bar );
print ( $baz );
?>
输出:
Only Created $bar and printing $bar
my name is " bar " and I live in " foo " .
Now $baz is referenced to $bar and printing $bar and $baz
my name is " bar " and I live in " foo " .
Now Creating MasterOne and Two and passing $bar to both constructors
Master : MasterOne | foo : my name is " bar " and I live in " foo " .
Master : MasterTwo | foo : my name is " bar " and I live in " foo " .
Now changing value of $bar and printing $bar and $baz
my name is " baz " and I live in " foo " .
my name is " baz " and I live in " foo " .
Now printing again MasterOne and Two
Master : MasterOne | foo : my name is " baz " and I live in " foo " .
Master : MasterTwo | foo : my name is " baz " and I live in " foo " .
Now changing MasterTwo ' s foo name and printing again MasterOne and Two
Master: MasterOne | foo: my name is "MasterTwo ' s Foo " and I live in " foo " .
Master: MasterTwo | foo: my name is " MasterTwo ' s Foo" and I live in "foo".
Also printing $bar and $baz
my name is "MasterTwo ' s Foo " and I live in " foo " .
my name is " MasterTwo ' s Foo" and I live in "foo".
上个例子解析:
$bar = new foo( ' bar ' );
$m1 = new MasterOne( $bar );
$m2 = new MasterTwo( $bar );
The $bar in the instance objects $m1 and $m2 is a reference to the instance $bar, not a copy. This is the characteristic of object references in php5, that is to say
1. Inside $m1 or $m2, any operation on $bar will affect the related value of the external object instance $bar.
2. Changes to the external object instance $bar will also affect the reference values of $bar inside $m1 and $m2.
In php4, to implement the above-mentioned method of using an object instance to refer to the properties of another object, the equivalent code (i.e. reference call) is similar to the following:
class foo{
var $bar ;
Function setBar( & $newBar ){
$this -> bar =& newBar;
}
}
5. The role of quotation
If the program is relatively large, there are many variables referencing the same object, and you want to clear it manually after using the object, I personally recommend using the "&" method, and then using $var=null to clear it. Otherwise, use the default of php5 Method. In addition, for transferring large arrays in php5, it is recommended to use the "&" method, after all, it saves memory space.
6. Unreference
When you unset a reference, you just break the binding between the variable name and the variable's contents. This does not mean that the variable contents are destroyed. For example:
$a = 1 ;
$b =& $a ;
unset ( $a );
?>
Doesn't unset $b, just $a.
7.global quote
When you declare a variable with global $var you actually create a reference to the global variable. That is the same as doing this:
$var =& $GLOBALS [ " var " ];
?>
This means that, for example, unset $var will not unset a global variable.
If a reference is assigned to a variable declared as global inside a function, the reference is only visible inside the function. This can be avoided by using the $GLOBALS array.
Example Reference global variables www.2cto.com within a function
$var1 = " Example variable " ;
$var2 = "" ;
function global_references( $use_globals )
{
global $var1, $var2;
If ( ! $use_globals ) {
} else {
$GLOBALS [ " var2 " ] =& $var1 ; // visible also in global context
}
}
echo " var2 is set to ' $var2 'n " ; // var2 is set to ''
global_references( true );
echo " var2 is set to ' $var2 'n " ; // var2 is set to 'Example variable'
?>
Think of global $var; as shorthand for $var =& $GLOBALS['var'];. Thus assigning another reference to $var only changes the reference to the local variable.
8.$this
In an object method, $this is always a reference to the object that calls it.
//Another little episode below
The address pointing (similar to a pointer) function in PHP is not implemented by the user himself, but is implemented by the Zend core. The reference in PHP adopts the principle of "copy-on-write", which means that unless a write operation occurs, it points to the same address. Variables or objects will not be copied.
1: If there is the following code
$a = " ABC " ;
$b =& $a ;
?>
In fact, $a and $b point to the same memory address at this time, rather than $a and $b occupying different memories
2: If you add the following code to the above code
$a = " EFG " ;
PHP references (that is, adding the ampersand in front of variables, functions, objects, etc.) is an advanced topic. Novices should pay attention. It is important to correctly understand PHP references, which has a great impact on performance, and misunderstanding may lead to program errors!
Many people misunderstand that references in PHP are the same as pointers in C. In fact, they are not, and they are very different. Except for the pointers in C language that do not need to be explicitly declared during the array transfer process, other points need to be defined using *. However, the pointer to address (similar to a pointer) function in PHP is not implemented by the user himself, but is implemented by the Zend core. Yes, the reference in PHP adopts the principle of "copy-on-write", that is, unless a write operation occurs, variables or objects pointing to the same address will not be copied, such as the following code:
$a = array ( ' a ' , ' c ' ... ' n ' );
$b = $a ;
If the program is only executed here, $a and $b are the same, but they do not occupy different memory spaces like C, but point to the same memory. This is the difference between php and c. There is no need to write $b=&$a to mean that $b points to the memory of $a. zend has already implemented the reference for you, and zend will be very smart to help you judge when you should do this and when you shouldn't. deal with.
If you continue to write the following code later, add a function, pass parameters by reference, and print out the array size.
function printArray( & $arr ) // Pass by reference
{
Print ( count ( $arr ));
}
printArray( $a );
In the above code, we pass the $a array into the printArray() function by reference. The zend engine will think that printArray() may cause changes to $a, and will automatically produce a data copy of $a for $b. , reapply a piece of memory for storage. This is the "copy-on-write" concept mentioned earlier.
If we change the above code to the following:
function printArray( $arr ) // Value passing
{
Print ( count ( $arr ));
}
printArray( $a );
The above code directly passes the $a value to printArray(). There is no reference transfer at this time, so there is no copy-on-write.
You can test the execution efficiency of the above two lines of code. For example, add a loop outside 1000 times and see how long it takes to run. The results will let you know that incorrect use of references will cause performance to drop by more than 30%.
Self-understanding: When passing by value, it has nothing to do with the parameters in the function, which is equivalent to the role of local variables, but when passing by address (reference), it is related to the parameters within the function, which is equivalent to the role of global variables. From a performance perspective, it is enough to look at the above analysis. .
What does a quote do
PHP's references allow two variables to point to the same content. Meaning, when doing this:
$a =& $b;
?>
This means $a and $b point to the same variable.
Note:
$a and $b are exactly the same here. It’s not that $a points to $b or vice versa, but that $a and $b point to the same place.
Note:
If an array with a reference is copied, its value will not be dereferenced. The same is true for passing array values to functions.
Note:
If an undefined variable is assigned by reference, passed by reference, or returned by reference, the variable will be automatically created.
Example #1 Using references to undefined variables
function foo(&$var) { }
foo($a); // $a is "created" and assigned to null
$b = array();
foo($b['b']);
var_dump(array_key_exists('b', $b)); // bool(true)
$c = new StdClass;
foo($c->d);
var_dump(property_exists($c, 'd')); // bool(true)
?>
The same syntax can be used in functions, which return references, and in the new operator (PHP 4.0.4 and later):
$bar =& new fooclass();
$foo =& find_var($bar);
?>
As of PHP 5, new automatically returns a reference, so using =& here is obsolete and produces an E_STRICT level message.
Note:
Not using the & operator causes a copy of the object to be generated. If you use $this in a class, it will apply to the current instance of that class. Assignment without & will copy the instance (e.g. object) and $this will be applied to the copy, which is not always the desired result. Due to performance and memory consumption issues, you usually only want to work on one instance.
Although it is possible to suppress any error messages in a constructor using the @ operator, such as @new, this has no effect when using a &new statement. This is a limitation of the Zend engine and will cause a parsing error.
Warning
If a reference is assigned to a variable declared global within a function, the reference is visible only within the function. This can be avoided by using the $GLOBALS array.
Example #2 Reference global variables within a function
$var1 = "Example variable";
$var2 = "";
function global_references($use_globals)
{
global $var1, $var2;
If (!$use_globals) {
$var2 =& $var1; // visible only inside the function
} else {
$GLOBALS["var2"] =& $var1; // visible also in global context
}
}
global_references(false);
echo "var2 is set to '$var2'n"; // var2 is set to ''
global_references(true);
echo "var2 is set to '$var2'n"; // var2 is set to 'Example variable'
?>
Think of global $var; as shorthand for $var =& $GLOBALS['var'];. Thus assigning another reference to $var only changes the reference to the local variable.
Note:
If a variable with a reference is assigned a value in a foreach statement, the referenced object is also changed.
Example #3 Quotation and foreach statement
$ref = 0;
$row =& $ref;
foreach (array(1, 2, 3) as $row) {
// do something
}
echo $ref; // 3 - last element of the iterated array
?>
The second thing that references do is pass variables by reference. This is accomplished by creating a local variable within the function and that variable references the same content in the calling scope. For example:
function foo(&$var)
{
$var++;
}
$a=5;
foo($a);
?>
will change $a to 6. This is because in function foo the variable $var points to the same thing that $a points to. See Passing by Reference for a more detailed explanation.
The third thing a reference does is to return a reference
A bug in array reference (later careful consideration, it is not actually a bug)
It appears that references can have side-effects. Below are two examples. Both are simply copying one array to another. In the second example, a reference is made to a value in the first array before the copy. In the first example the value at index 0 points to two separate memory locations. In the second example, the value at index 0 points to the same memory location.
I won't say this is a bug, because I don't know what the designed behavior of PHP is, but I don't think ANY developers would expect this behavior, so look out.
An example of where this could cause problems is if you do an array copy in a script and expect on type of behavior, but then later add a reference to a value in the array earlier in the script, and then find that the array copy behavior has unexpectedly changed.
// Example one
$arr1 = array (1);
echo " nbefore:n " ;
echo " $arr1[0] == { $arr1 [0]}n " ;
$arr2 = $arr1 ;
$arr2 [ 0 ] ++ ;
echo " nafter:n " ;
echo " $arr1[0] == { $arr1 [0]}n " ;
echo " $arr2[0] == { $arr2 [0]}n " ;
Output:
before:
$arr1[0] == 1
after:
$arr1[0] == 1
$arr2[0] == 2
// Example two
$arr3=array(1);
$a=&$arr3[0];
echo"nbefore:n";
echo "$a == $an";
echo "$arr3[0] == {$arr3[0]}n";
$arr4=$arr3;
$arr4[0]++;
echo"nafter:n";
echo "$a == $an";
echo "$arr3[0] == {$arr3[0]}n";
echo "$arr4[0] == {$arr4[0]}n";
Output:
before:
$a == 1
$arr3[0] == 1
after:
$a == 2
$arr3[0] == 2
$arr4[0] == 2
?>
Analysis description:
Regarding "Example two", I thought it was a bug at first. In fact, after careful consideration, it is not wrong. The analysis is as follows,
Assignment (copy)
$arr4 = $arr3 ;
, there is a process of establishing a reference to the first element of $arr3, that is,
$a =& $arr3 [ 0 ];
So in the subsequent assignment copy ( $arr4=$arr3; ), this reference will be copied together, so
$a, $arr3[0], $arr4[0] are actually reference relationships, pointing to the same place.
Excerpted from PPP