PHP变量、引用、函数传参之完全掌握,今后节操是路人

今天绝对是兴奋的一天,不单单是周五这个特殊的日子(周六日能够休息啦),也不是弄清了某wordpress插件的功能流程,更不是再次买到了想吃好久的手撕牛肉,而是真正解决了一直以来(嘿嘿,其实时间不长)对PHP中变量引用和函数传参的疑惑。 php

故事源于一个巧合,我在查PHP变量做用域的东西时看到的文章(后面再附上地址,无心侵权做者大大)。由于这篇只讲变量和函数传参的,因此其余的不涉及了(也无力涉及哈哈)。 html

看这么一句 wordpress

$a = 'abc';

当咱们定义一个变量时,PHP会为咱们作两件事情 函数

  1. 申请一个zval结构体,那什么是zval呢
    struct _zval_struct {
            /* Variable information */
            zvalue_value value;             /* value */
            zend_uint refcount;
            zend_uchar type;        /* active type */
            zend_uchar is_ref;
    };
    这个就是zval的C语言定义,在PHP中变量都是用这个结构体来存储,其中成员zvalue_value是一个联合体,用以存储底层强类型变量,这种结构也是实现PHP弱类型的关键,在这里只须要清楚有这么个结构体就能够了。
  2. zval结构体存实际内容(最最里面实际上是那个union体),令变量名符号a指向这个zval,而后将a存在一个symbol_table中,这个symbol_table跟变量的做用域有关,这里不作讨论,只需知道一个变量是一个符号指向一个zval结构体就好。 
看下面代码:
$a = 12;
$b = $a;

执行到第二句时,会在symbol_table中新加入b,令b指向a所指向的那个zval结构体,这个zval的refcount加1, 到这根据以往的知识可能就有疑问了,b指向a指向的结构体不就是引用了嘛,再看下面代码: ui

$a = 12; $b = &$a;

那这算什么?执行第二句时,除了在symbol_table中加入b令其指向a指向的那个zval并使refcount加1外,还会改变该zval中is_ref值为1(默认为零应该),is_ref是个bool值,用来标识这个变量是不是属于引用集合(reference set)这样这个zval就与一开始不太同样了。 spa

来看更复杂的: .net

$a = 12;
$b = $a;
$c = &$a;

前两行执行完与前面第一个例子是同样的,此时$a和$b指向的zval的refcount值为2,is_ref为0,表示有两个symbol指向这个zval, is_ref为0,表示zval不属于引用集合,当第三行执行时时,发现zval的refcount不为1且不是引用集合,那么便为$b复制一个zval结构体,同时$a的zval的refcount减1,又由于多了$c指向原来的zval,因此又refcount加1,仍是2,同时$a也是$c的zval的is_ref置1,表示这个zval属于引用集合了,$b的zval则是新的zval(refcount=1,is_ref=0)。 插件

第二、3行交换位置最后的结果相同,只不过zval的变化顺序不一样,最终仍然是$a与$c指向同一个zval(refcount=2,is_ref=1),$b指向的zval(refcount=1,is_ref=0)。 code

再有$d、$e等原理同样。 orm

当更改变量时也会发生zval的新建与变化,原理同上,不细讨论了,可参见:

  1. http://php.net/manual/zh/features.gc.refcounting-basics.php(复合类型的变量也有讲到)
  2. http://www.laruence.com/2008/09/19/520.html(L大大写的真的很棒) 

当咱们明白了这个机制的时候,函数传参就迎刃而解了:

$a = 12;
function change($k){
    $k = 1;
}

change(&$a);  //至关于$k = &$a,接下来就知道怎么办了吧,$a的值是能够改变的



change($a);   //至关于$k = $a,你看,还用我说么?
好的,到这就差很少了,要是我写的有点乱很差懂(不是深奥,我有自知之明的),好好研究下上面两个网址。

恩,这篇写的好累,休息休息 

相关文章
相关标签/搜索