我们首先看下官方英文文档的解释。
PHP中的引用意味着你可以用不同的变量名访问同一个变量内容。在PHP中变量名和变量内容是不同的,引用是符号表别名。引用不同于C语言中的指针,你不能对其进行数学运算。最形象的比喻就是Unix的文件系统,变量名对应文件系统中的文件名,而变量内容对应文件系统中实际的文件内容,引用即为系统中的硬链接。
那么PHP中的引用和C语言中的指针有什么不同呢?C语言中加入定义一个整形指针“int *p”,我们可以对指针进行加操作“p++”,那么它就指向了下一个内存地址。或者我们进行赋值操作,给指针p一个新的地址“p = n”,那么p就指向了n所指向的地址,他们都指向同一个地址。而在PHP中我们不可以对引用使用加减操作,因为通过引用赋值时,如“$b=&$a”,新的$b只是一个变量名而已,和$a是一样的,&的作用就是使$b的变量内容指向了$a的变量内容,$b终究只是一个变量名,用官方的说法是$a的别名。说的直白点就是,使用了“&”的话就不会分配新的内存空间,引用的结果是新变量指向现有的内存空间。
PHP中引用的作用是什么呢?引用有三个基本的作用:引用赋值、引用传递和引用返回。
引用赋值
对于“$a=$b”,$a和$b是完全一样的,他们都指向同一个内容。
引用传递
PHP中函数参数的传递都是值传递,都是将实参的值拷贝一份传递到函数中。如果想在函数中修改函数外部的值,那么就需要引用。
引用返回
可以使用引用进行函数返回,而不是返回值的拷贝。
具体的作用介绍可参考http://php.net/manual/en/language.references.whatdo.php。
需要我们注意的是,在PHP5中的对象变量,我们需要深刻理解。PHP5中的对象变量已经不再保存整个对象的值,只是保存一个标识符来访问真正的对象内容。当对象作为参数传递,作为结果返回,或者赋值给另外一个变量,另外一个变量跟原来的不是引用的关系,只是他们都保存着同一个标识符的拷贝,这个标识符指向同一个对象的真正内容。 可以参考下列代码对本篇文章进行理解。
<?php $a = 1; $b = $a; $b = 4; echo $a . '<br>'; // 1 $b = &$a; $b = 4; echo $a . '<br>'; // 4 $c = $b; $c = 5; echo $b . '<br>'; // 4 echo $a . '<br><br>'; // 4 $a= 1; function func (&$args){ $args = 6; } func($a); echo $a; // 6 ?>
对象变量的引用
<?php class A { public $foo = 'empty'; } class B { public $foo = 'empty'; public $bar = 'hello'; } function normalAssignment($obj) { $obj->foo = 'changed'; $obj = new B; } function referenceAssignment(&$obj) { $obj->foo = 'changed'; $obj = new B; } $a = new A; normalAssignment($a); echo get_class($a), "\n"; echo "foo = {$a->foo}\n"; referenceAssignment($a); echo get_class($a), "\n"; echo "foo = {$a->foo}\n"; echo "bar = {$a->bar}\n"; /* prints: A foo = changed B foo = empty bar = hello */ ?>
代码中可以看出,普通变量的变量内容存储的就是实际的变量内容,而对象变量的变量内容实际上是对象的标志符,而不是正真的对象。例如将上述代码中的$a赋值给$b,“$b=$a”所代表的意义是创建一个新的变量$b,$b的变量内容存储的值和变量$a的变量内容所存储的值是一样的,都是对象的标识符,而且这两个变量具有不同的变量内容存储空间。而引用赋值“$b=$a”所代表的意义是变量$b的变量内容指向变量$a的变量内容,这两个变量的变量内容都指向一个存储空间。“=”和“=&”操作得到的变量都可对对象的值进行修改,若想在函数中修改对象的值,则在函数定义时可不必加“&”操作符。PHP5中对象的赋值操作不会产生新的对象,要复制对象,使用clone关键字。