[PHP]引用语法

一、概述

在php中,引用意味着用不同的symbol指向同一个变量内容。它的大致语法是:

symbol_a =& symbol_b 

它的正确解读方法是:把symbol_a的指向改变成指向symbol_b指向的结果上

示例:

$a = 1;
$b =& $a;
$a = 2;
var_dump($b);//output 2

在php结果的数据结构中,每个结果都有一个指向字段,表明这个结果被多少个symbol指向;

示例中表达式『$a = 1』中,编译器会创建一个symbol和一个结果,这个结果只有一个symbol指向它,是刚创建的『$a』;

接下来表达式『$b =& $a』则只创建了一个symbol『$b』,这个symbol和『$a』一样,共同指向了一个结果;

引用的操作将symbol『$b』与symbol『$a』指向了同一个结果,当结果增加一个指向,那么它的指向字段就会加1,相反,unset()一个symbol会导致结果的指向字段减1,直到结果的指向字段为0,CG将其清除;

这种操作有点类似于Unix的文件系统;

二、和C语言的寻址运算符的差别

c语言的变量可以用来保存一个地址值,『&』则作为寻址运算符,在变量前面加『&』的语义是求该变量的内存地址,然后赋值到另一个变量上,通过间接运算符『*』去读取地址指向的内容;

在c语言中,『&』是单独的语义;

而php则不是,根据『&』号出现的位置,有不同的解读,在下述表格先列出可以出现『&』号的位置,稍后小结会对某些结合了『&』的语句进行单独解读;

表达式 语义
$foo =& $bar 改变$foo的引用至$bar的引用
function foo(&$bar){} 改变$bar的引用至外部参数的引用
function &foo(){return $a;} 返回$a的引用
foreach($foo AS $key => &$value) 改变$value的引用至$foo的当前遍历项(原本$value只是当前遍历项的复制值)

 

看看这个例子:

<?php
function foo(&$var)
{
    $var =& $GLOBALS["baz"];
}
foo($bar);
?>

如果按照c语言的思维去理解,它本应该会是这样的:

  • 假设函数外部『$bar』是一个指针变量;
  • 进入foo()环境,『$var』变量被创建;
  • 『$var』被赋值为指向外部变量『$bar』的地址,函数内部把『$baz』的地址赋值给这个地址;
  • 『$bar』指向的内容被改变了,换成了指向外部『$baz』的值;

而php是这样做的:

  • 进入foo()环境,『$var』symbol被创建;
  • 由于在函数参数声明中带有『&』运算符,所以symbol『$var』在创建后马上把指向改为跟『$bar』指向相同的一个值,『$bar』的值引用次数加1;
  • 紧接着symbol『$var』的指向再次被表达式『$var =& $GLOBALS["BAZ"]』改变为指向指向外部『$baz』的值,『$baz』的值引用次数减1,『$baz』的值引用次数加1;
  • 最后函数结束symbol『$var』被销毁,『$baz』的值引用次数减1;

看到没,函数内部改变的,只不过是内部创建的『$var』的指向,而『$var』在函数退出后就被销毁了,跟『$bar』断绝了关系;

 

三、引用返回

『&』号除了可以用在变量赋值表达式1当中,也可以用在函数结构当中,函数名前面加『&』号表明这个函数返回一个引用:

<?php
class foo {
    public $value = 42;

    public function &getValue() {
        return $this->value;
    }
}

$obj = new foo;
$myValue = &$obj->getValue(); // $myValue is a reference to $obj->value, which is 42.
$obj->value = 2;
echo $myValue;                // prints the new value of $obj->value, i.e. 2.
?>

如上述例子所示,为了改变一个symbol的引用,变量赋值表达式1也需要加『&』。

注1:严格来说应该叫做改变变量引用表达式。

四、引用传递

当函数参数是一个引用值,那么调用这个函数的入参只能是以下3种形式:

  1. 变量,例如foo($a);
  2. new语句,例如foo(new bar());
  3. 从函数中返回引用,例如:
<?php
function &bar()
{
    $a = 5;
    return $a;
}
foo(bar());
?>
posted @ 2020-05-26 10:34  yiyide266  阅读(177)  评论(0编辑  收藏  举报