HP手册》变量》可变变量》全局和静态变量的引用
定义:引用做的第二件事是用引用传递变量,这是通过在函数内建立一个本地变量并且该变量在呼叫范围内引用了同一个内容来实现的
代码:
分析代码:
图例1:
分析过程:
代码1:
PHP脚本在全局中,声明了一个 a 变量,并为其赋值一个整型值 5
代码2:
xdebug运行结果 a:(refcount=1, is_ref=0), int 5
由代码2的xdebug运行结果,我们分析出代码1,在内存中产生了一个zval"容器",也可以作为"盒子",这里我叫容器
is_ref:代表这个"容器"是否被引用,1 引用 0 默认
refcount:代表有多少变量指向这个"容器"
refcount=1说明当前有一个变量正在指向这个容器,那就$a, is_ref=0代表当前只有一个变量指向该容器,这个我在global分析中,解释过这个问题,不理解的可以先看下global分析过程
代码3:
然后我们调用了foo 函数,并将 a变量 以参数的形式传入,执行函数体内部的代码
但在分析函数内部的代码之前,还是先看一下函数的参数,形参和实参
形参:函数声明时定义的参数
实参:函数调用时传入的参数
形参和实参一一对应,其实就是"赋值关系",将实参赋给形参
由上分析得出,foo函数在调用时传入a 变量,然后函数在声明时定义了引用传参 &$var , 就相当于 $var = &$a,这只是从定义或术语的角度去分析了一下,接下来我们用xdebug来跟踪一下
代码3的 xdebug 运行结果:
var : (refcount=3 , is_ref=1) , int 5
函数调用时,将全局的变量a 传入,且将a变量引用赋值给函数内部变量 var,所以全局的变量 a 和函数内部 变量 var, 同指向同一个zval容器,所以这个zval容器的 is_ref 为1 ,代表这个容器变量指向关系是引用的
现在有两个变量正在指向这个zval容器,refcount=3代表有3个变量正在指向这个zval容器,那还有一个变量是什么,这个变量属于全局的,还是函数内部的?
图例2:
为了解答上述提出的疑问,我们在原有的代码基础上,增加了代码4
代码4 的xdebug运行结果:
a : (refcount= 3 , is_ref=1) , int 5
分析:
由代码4的xdebug结果中分析出,函数内部也创建了一个a变量,且和 全局变量a、函数内部变量 var 同指向一个zval容器
还记得分析global的情况吗?
函数内部声明的global 变量 ,其实在函数内部创建一个和全局变量一样的函数局部变量,且这个局部变量和全局变量同指向同一个zval容器,并保持引用关系
其实函数的引用传参 和 传值传参也是同样的道理
当调用函数foo,并传入全局变量a时,先在函数内部创建一个和全局变量同样的 a变量 ,且把这个a变量 指向全局变量 a ,所指向的zval容器,且这两个变量之间保持引用关系
然后在将 函数内部变量 a 引用赋值给 函数内部变量 var
这样函数内部 var 变量,和函数内部a、全局变量 a 指向同一个zval容器,且引用,这也解释了 refcount=3,3个变量从哪里来的
这样 var++,将会影响全局变量a和局部变量a
当函数执行完成后,申请的内容空间就会被释放掉了,所以只剩了全局变量 a 在指向原来的zval容器,但值已经被改成了6
函数的 传值传参
代码:
分析代码:
图例3:
分析过程:
代码1和代码2:
xdebug运行结果:
var : (refcount=3 , is_ref=0) , int 5
a : (refcount=3 , is_ref=0) , int 5
由上图分析得出,函数的引用传参和传值传参,并没多大区别,唯一区别在于变量所指向的zval是否是引用的,但是传参的时候,还是都要在局部内创建一个和全局一样的变量,且指向同一个zval容器(因为值一样,所以指向同一个容器,节省了内存开销),因为函数的传值传参和 引用传参一样,我也就省略了函数的传值传参分析过程,分析同引用传参.
总结:
在函数调用传入参数后,先在函数内部创一个同传入参数一样的变量,且新创建的函数内部变量,和传入参数,同时指向内存中的同一区域,如果函数参数声明为引用则互相影响,如果没声明为引用则只是在函数内部创了一个同传入参数一样的变量,同时值也一样,但互不影响,因为一个是全局变量,一个是函数局部变量(虽然变量名一样,值一样).
定义:引用做的第二件事是用引用传递变量,这是通过在函数内建立一个本地变量并且该变量在呼叫范围内引用了同一个内容来实现的
代码:
分析代码:
图例1:
![2014-09-02_103709.png 2014-09-02_103709.png](http://www.zixue.it/data/attachment/forum/201409/02/1038342l3n3e2hl2ffjhhh.png)
分析过程:
代码1:
PHP脚本在全局中,声明了一个 a 变量,并为其赋值一个整型值 5
代码2:
xdebug运行结果 a:(refcount=1, is_ref=0), int 5
由代码2的xdebug运行结果,我们分析出代码1,在内存中产生了一个zval"容器",也可以作为"盒子",这里我叫容器
is_ref:代表这个"容器"是否被引用,1 引用 0 默认
refcount:代表有多少变量指向这个"容器"
refcount=1说明当前有一个变量正在指向这个容器,那就$a, is_ref=0代表当前只有一个变量指向该容器,这个我在global分析中,解释过这个问题,不理解的可以先看下global分析过程
![2014-09-02_094336.png 2014-09-02_094336.png](http://www.zixue.it/data/attachment/forum/201409/02/094421qyinnlgzgonnnig4.png)
代码3:
然后我们调用了foo 函数,并将 a变量 以参数的形式传入,执行函数体内部的代码
但在分析函数内部的代码之前,还是先看一下函数的参数,形参和实参
形参:函数声明时定义的参数
实参:函数调用时传入的参数
形参和实参一一对应,其实就是"赋值关系",将实参赋给形参
由上分析得出,foo函数在调用时传入a 变量,然后函数在声明时定义了引用传参 &$var , 就相当于 $var = &$a,这只是从定义或术语的角度去分析了一下,接下来我们用xdebug来跟踪一下
代码3的 xdebug 运行结果:
var : (refcount=3 , is_ref=1) , int 5
函数调用时,将全局的变量a 传入,且将a变量引用赋值给函数内部变量 var,所以全局的变量 a 和函数内部 变量 var, 同指向同一个zval容器,所以这个zval容器的 is_ref 为1 ,代表这个容器变量指向关系是引用的
![2014-09-02_110745.png 2014-09-02_110745.png](http://www.zixue.it/data/attachment/forum/201409/02/110839rt855jty0zj95hqb.png)
现在有两个变量正在指向这个zval容器,refcount=3代表有3个变量正在指向这个zval容器,那还有一个变量是什么,这个变量属于全局的,还是函数内部的?
图例2:
![2014-09-02_104802.png 2014-09-02_104802.png](http://www.zixue.it/data/attachment/forum/201409/02/1049215xbz709o37q3bhsd.png)
为了解答上述提出的疑问,我们在原有的代码基础上,增加了代码4
代码4 的xdebug运行结果:
a : (refcount= 3 , is_ref=1) , int 5
分析:
由代码4的xdebug结果中分析出,函数内部也创建了一个a变量,且和 全局变量a、函数内部变量 var 同指向一个zval容器
![2014-09-02_111632.png 2014-09-02_111632.png](http://www.zixue.it/data/attachment/forum/201409/02/1117293ni534c656fcll7r.png)
还记得分析global的情况吗?
函数内部声明的global 变量 ,其实在函数内部创建一个和全局变量一样的函数局部变量,且这个局部变量和全局变量同指向同一个zval容器,并保持引用关系
其实函数的引用传参 和 传值传参也是同样的道理
当调用函数foo,并传入全局变量a时,先在函数内部创建一个和全局变量同样的 a变量 ,且把这个a变量 指向全局变量 a ,所指向的zval容器,且这两个变量之间保持引用关系
![2014-09-02_113201.png 2014-09-02_113201.png](http://www.zixue.it/data/attachment/forum/201409/02/1132480j6djhiz6j00lzd0.png)
然后在将 函数内部变量 a 引用赋值给 函数内部变量 var
![2014-09-02_114046.png 2014-09-02_114046.png](https://i-blog.csdnimg.cn/blog_migrate/289090405644bab67e30c81a2a148446.png)
这样函数内部 var 变量,和函数内部a、全局变量 a 指向同一个zval容器,且引用,这也解释了 refcount=3,3个变量从哪里来的
这样 var++,将会影响全局变量a和局部变量a
![2014-09-02_115156.png 2014-09-02_115156.png](http://www.zixue.it/data/attachment/forum/201409/02/11525991ea0c0ca9daa0b9.png)
当函数执行完成后,申请的内容空间就会被释放掉了,所以只剩了全局变量 a 在指向原来的zval容器,但值已经被改成了6
![2014-09-02_115521.png 2014-09-02_115521.png](http://www.zixue.it/data/attachment/forum/201409/02/115612r2ceemksimejsrkw.png)
函数的 传值传参
代码:
分析代码:
图例3:
![2014-09-02_131954.png 2014-09-02_131954.png](https://i-blog.csdnimg.cn/blog_migrate/a16e9140ea60e79cf0e196444bbb1524.png)
分析过程:
代码1和代码2:
xdebug运行结果:
var : (refcount=3 , is_ref=0) , int 5
a : (refcount=3 , is_ref=0) , int 5
![2014-09-02_132259.png 2014-09-02_132259.png](https://i-blog.csdnimg.cn/blog_migrate/b535f5c76d47632d335ee01d863cca54.png)
由上图分析得出,函数的引用传参和传值传参,并没多大区别,唯一区别在于变量所指向的zval是否是引用的,但是传参的时候,还是都要在局部内创建一个和全局一样的变量,且指向同一个zval容器(因为值一样,所以指向同一个容器,节省了内存开销),因为函数的传值传参和 引用传参一样,我也就省略了函数的传值传参分析过程,分析同引用传参.
总结:
在函数调用传入参数后,先在函数内部创一个同传入参数一样的变量,且新创建的函数内部变量,和传入参数,同时指向内存中的同一区域,如果函数参数声明为引用则互相影响,如果没声明为引用则只是在函数内部创了一个同传入参数一样的变量,同时值也一样,但互不影响,因为一个是全局变量,一个是函数局部变量(虽然变量名一样,值一样).