There are two ways of assigning values in PHP Syntax: reference assignment, non-reference assignment.
$a = 1;
$b = $a; Non-reference assignment
$c = & $b; Reference assignment
$a = 1;
$b = $a; Non-reference assignment
$c = & $b; Reference assignment
On the surface, it is usually said that "the reference assignment is two variables corresponding to the same variable (in C is actually a zval), the non-reference assignment is a direct result of a new variable (zval), while the value is copied".
This thought can be figured out in most cases. (#1)
But in some cases it can be very inefficient, for example: (#2)
function Print_arr ($arr) {//non-reference delivery
Print_r ($arr);
}
$test _arr = Array (
' A ' = ' a ',
' B ' = ' B ',
' C ' = ' C ',
...
);//Here is a larger array
Print_arr ($test _arr);//First call Print_arr function execution output
Print_arr ($test _arr);//second call to Print_arr function execution output
function Print_arr ($arr) {//non-reference delivery
Print_r ($arr);
}
$test _arr = Array (
' A ' = ' a ',
' B ' = ' B ',
' C ' = ' C ',
...
);//Here is a larger array
Print_arr ($test _arr);//First call Print_arr function execution output
Print_arr ($test _arr);//second call to Print_arr function execution output
If you follow the above understanding (#1), then execute two times Print_arr, and the non-reference way, it will produce two identical with $test_arr new variable, then it will be very inefficient.
The actual code is running and does not produce two new variables. Because the PHP kernel has helped us to optimize.
How is it implemented? Here are the main points of this article: Reference counting & Copy-on-write, which are optimized using the two mechanisms of reference counting and copy-on-write.
Before introducing these two mechanisms, let's look at the basics: How variables in PHP are represented in the kernel.
Variables defined in PHP are represented by a zval, and the definition of zval is defined in Zend/zend.h:
typedef struct _ZVAL_STRUCT Zval;
typedef Union _ZVALUE_VALUE {
Long lval; /* Long value */
Double Dval; /* Double Value */
struct {
Char *val;
int Len;
} str;
HashTable *ht; /* Hash Table value */
Zend_object_value obj;
} Zvalue_value;
struct _zval_struct {
/* Variable Information */
Zvalue_value value; /* Value */
Zend_uint RefCount;
Zend_uchar type; /* Active type */
Zend_uchar Is_ref;
};
typedef struct _ZVAL_STRUCT Zval;
typedef Union _ZVALUE_VALUE {
Long lval; /* Long value */
Double Dval; /* Double Value */
struct {
Char *val;
int Len;
} str;
HashTable *ht; /* Hash Table value */
Zend_object_value obj;
} Zvalue_value;
struct _zval_struct {
/* Variable Information */
Zvalue_value value; /* Value */
Zend_uint RefCount;
Zend_uchar type; /* Active type */
Zend_uchar Is_ref;
};
Among them, RefCount and is_ref are the basis for implementing the two mechanisms of reference counting, write-time replication.
RefCount the current variable stores the reference count, which is 1 when the Zval is initially created. Each additional reference is RefCount + +. When a reference is detached, the RefCount--。
Is_ref is used to indicate whether a zval is a reference state. The Zval initialization will be 0, which means it is not a reference.
$a;//a:refcount=1,is_ref=0, value=null;
$a = 1; A:refcount=2,is_ref=0, value=1;
$b = $a; a,b:refcount=3,is_ref=0,value=1;
$c = $a; a,b,c:refcount=4,is_ref=0,value=1;
$d = & $c; a,b:refcount=3,is_ref=0,value=1; C,d:refcount=1, Is_ref=1, value=1
$a;//a:refcount=1,is_ref=0, value=null;
$a = 1; A:refcount=2,is_ref=0, value=1;
$b = $a; a,b:refcount=3,is_ref=0,value=1;
$c = $a; a,b,c:refcount=4,is_ref=0,value=1;
$d = & $c; a,b:refcount=3,is_ref=0,value=1; C,d:refcount=1, Is_ref=1, value=1 comments on the above code, indicating changes in RefCount and is_ref after this line is executed.
Copy on Write
PHP variables share data by reference counting, so what if you change one of the variable values?
When attempting to write a variable, Zend discovers that the variable points to the Zval is shared by more than one variable, it copies a copy of Ref_count 1 zval, and decrements the zval of the original refcount, this process is called "Zval separation." Visible, the copy operation is only performed when there is a write operation, so it is also called copy-on-write (copy on Zend).
For reference variables, the requirement is the opposite of the non-reference type, and the variable that references the assignment must be bundled, and modifying a variable modifies all the bundle variables.
$a = 1;
$b = $a;
$a = 1;
$b = $a; the memory structure diagram during execution:
$a = 1;
$b =&a;
$a = 1;
$b =&a; the memory structure during execution:
As you can see, this direct assignment does not produce a new variable, whether it is a reference or a non-reference.
Is_ref is set to 1 only when it is a reference. When not referenced, Is_ref is set to 0.
Read-write replication is the separation of variables according to Is_ref.
When is_ref=1 is a reference variable, perform a "variable separation under reference"
$a = 1;
$b = $a;
$c = & $b;
$a = 1;
$b = $a;
$c = & $b; Memory structure diagram during execution:
Perform "Non-reference variable detach" when is_ref=0 is non-reference variable
$a = 1;
$b = & $a;
$c = $b;
$a = 1;
$b = & $a;
$c = $b;
Memory structure diagram during execution:
Only if you really need to change the value of the variable,
Looking back at the (#2) code, you can see that in fact, there is no new variable generated, always the $test_arr variable in the output. So, that's why it's very rare to see passing variables in PHP with reference, but there's still no performance problem.
Excerpt from God's blog
http://www.bkjia.com/PHPjc/478512.html www.bkjia.com true http://www.bkjia.com/PHPjc/478512.html techarticle There are two ways to assign values in PHP syntax: reference assignment, non-reference assignment. php $a = 1; $b = $a;//non-reference assignment $c = $b;//reference assignment? php $a = 1; $b = $a;//non-reference assignment $c ...