国内最全IT社区平台 联系我们 | 收藏本站
阿里云优惠2流量王
您当前位置:首页 > php开源 > php教程 > PHP引用传递与引用&一些用法介绍

PHP引用传递与引用&一些用法介绍

来源:程序员人生   发布时间:2014-05-15 20:12:44 阅读次数:868次

引用是什么

在 PHP 中引用意味着用不同的名字访问同一个变量内容,这并不像 C 的指针,替代的是,引用是符号表别名,注意在 PHP 中,变量名和变量内容是不一样的,因此同样的内容可以有不同的名字,最接近的比喻是 Unix 的文件名和文件本身——变量名是目录条目,而变量内容则是文件本身,引用可以被看作是 Unix 文件系统中的 hardlink。

引用做什么

PHP 的引用允许用两个变量来指向同一个内容。

当 $a =& $b; 时 $a 和 $b 指向了同一个变量。

提示:$a 和 $b 在这里是完全相同的,这并不是 $a 指向了 $b 或者相反,而是 $a 和 $b 指向了同一个地方。

可以将一个变量通过引用传递给函数,这样该函数就可以修改其参数的值,语法如下:

  1. <?php  
  2. function foo(&$var)  
  3. {  
  4.     $var++;  
  5. }  
  6.    
  7. $a=5;  
  8. foo($a);  
  9. echo $a
  10. // 输出的是:6 

PHP引用符&

关于php的引用(就是在变量或者函数、对象等前面加上&符号)的作用,我们先看下面这个程序。代码如下:

  1. <?php 
  2. $a = 100; //声明变量a 
  3. $b = &$a//声明变量b,引用自变量a 
  4. echo "$a <br />";   
  5. echo "$b <br />"
  6. $a++; //变量a自增1 
  7. echo "$a <br />"
  8. echo "$b <br />";//查看变量b,也增加了1,说明使用的是同一存储单元 
  9. ?> 
  10. //程序运行结果: 
  11. //100  
  12. //100  
  13. //101  
  14. //101 

很多人误解php中的引用跟C当中的指针一样,事实上并非如此,而且很大差别。C语言中的指针除了在数组传递过程中不用显式申明外,其他都需要使用*进行定义,而php中对于地址的指向(类似指针)功能不是由用户自己来实现的,是由Zend核心实现的,php中引用采用的是“写时拷贝”的原理,就是除非发生写操作,指向同一个地址的变量或者对象是不会被拷贝的。

php默认为传值传递,代码如下:

  1. <?php     
  2. $a = 20; 
  3. $b = $a
  4. $a = $a + 10;  
  5. echo $a.' and '.$b;  
  6. ?> 
  7. //程序运行结果: 
  8. //30 and 20 

要是想变为地址传递需要加&,既代码如下:

  1. <?php 
  2. $a = 20; 
  3. $b = &$a;  
  4. $a = $a + 10;  
  5. echo $a.' and '.$b;  
  6. ?> 

就是说,&把$a的地址传给了$b,这样的话这两个变量现在共享一个内存的存储区域,就是说它们的值是一样的。

同样的语法可以用在函数中,它返回引用,以及用在 new 运算符中,代码如下:

  1. <?php  
  2. $bar =& new fooclass();  
  3. $foo =& find_var($bar);  
  4. ?> 

引用做的第二件事是用引用传递变量,这是通过在函数内建立一个本地变量,并且该变量在呼叫范围内引用了同一个内容来实现的,说的通俗点就是一个函数的参数是一个本地变量的引用,下面再举例说明一下:

  1. <?php 
  2. function foo(&$val1$val2) { 
  3.  $val1 += 1; 
  4.  $val2 += 1; 
  5. $a=5; 
  6. $b=10; 
  7. foo($a,$b); 
  8. echo $a
  9. echo $b
  10. ?> 

运行这段代码是给函数传递两个参数,一个是引用$a的内容,一个是$b的值,在执行此函数后,发现$a的内容改变了,而$b的内容则没有变化。

PHP引用以及误区

PHP中的引用可以理解成变量的别名,由于PHP的变量名是存储在符号表(symbol table)中的,变量内容是存储在堆中,引用就是用符号表中的不同符号(symbol)名称来访问同一存储内容,和Unix文件系统中的hardlink是同一个概念,比如实例代码如下:

  1. <?php 
  2. $a = 1; 
  3. $b = &$a//$a与$b指向同一内容 
  4. $b = 2; 
  5. echo $b//2 
  6. echo $a//2 
  7. ?> 

传递引用

引用传递很简单,就是一个「&」符号,比如如下代码:

  1. <?php 
  2. function foo(&$a) { 
  3.   $a = 2; 
  4. $b = 1; 
  5. foo($b); 
  6. echo $b//2 
  7. ?> 

返回引用

大多数情况下并不需要返回引用来提高性能,zend引擎会自己进行优化,但是如果你非得返回引用得话,可以按照以下方式来返回引用,代码如下:

  1. <?php 
  2. class foo { 
  3.     public $value = 42; 
  4.     public function &getValue() { // 需要一个"&" 
  5.         return $this->value; 
  6.     } 
  7. $obj = new foo; 
  8. $myValue = &$obj->getValue(); // 还需要一个"&",$myValue是对class foo中的$value的引用 
  9. $obj->value = 2;              // 修改对象的$value属性 
  10. echo $myValue;                // 输出2,$myValue与class foo中的$value值相同 
  11. ?> 

与指针的区别

引用与指针很像,但是其并不是指针,看如下的代码:

  1. <?php 
  2.     $a = 0; 
  3.     $b = &a; 
  4.     echo $a//0 
  5.     unset($b); 
  6.     echo $a//0 
  7. ?> 

由于$b只是$a的别名,所以即使$b被释放了,$a没有任何影响,但是指针可不是这样的,看如下代码:

  1. #include <stdio.h> 
  2. int main(int argc, char const *argv[]) { 
  3.     int a = 0; 
  4.     int* b = &a; 
  5.     printf("%in", a); //0 
  6.     free(b); 
  7.     printf("%in", a); //*** error for object 0x7fff6350da08: pointer being freed was not allocated 

由于b是指向a的指针,所以释放了b的内存之后,再访问a就会出现错误,比较明显的说明了PHP引用与C指针的区别。

对象与引用

在PHP中使用对象的时候,大家总是被告知“对象是按照引用传递的”,其实这是个误区,PHP的对象变量存储的是此对象的一个标示符,在传递对象的时候,其实传递的就是这个标示符,而并不是引用,看如下代码:

  1. <?php 
  2. $a = new A; 
  3. $b = $a;     
  4. $b->testA = 2; 
  5. /* 
  6.  * 此时$a,$b的关系: 
  7.  *        +-----------+      +-----------------+ 
  8.  * $a --> | object id | ---> | object(Class A) | 
  9.  *        +-----------+      +-----------------+ 
  10.  *                               ^ 
  11.  *        +-----------+          | 
  12.  * $b --> | object id | ---------+ 
  13.  *        +-----------+     
  14.  * 
  15.  * 
  16.  */ 
  17. $c = new B; 
  18. $a = $c
  19. $a->testB = "Changed Class B"
  20. /* 
  21.  * 此时$a,$b,$c的关系: 
  22.  *        +-----------+      +-----------------+ 
  23.  * $b --> | object id | ---> | object(Class A) | 
  24.  *        +-----------+      +-----------------+ 
  25.  *                                
  26.  *        +------------+           
  27.  * $a --> | object id2 | -------------+ 
  28.  *        +------------+              | 
  29.  *                                    v 
  30.  *        +------------+      +-----------------+ 
  31.  * $c --> | object id2 | ---> | object(Class B) | 
  32.  *        +------------+      +-----------------+ 
  33.  */ 
  34. echo "object a: "; var_dump($a); //["testB"]=> string(15) "Changed Class B" 
  35. echo "object b: "; var_dump($b); //["testA"] => int(2) 
  36. echo "object c: "; var_dump($c); //["testB"]=> string(15) "Changed Class B" 
  37. ?> 

如果对象是按照引用传递的,那么$a, $b, $c输出的内容应该一样,事实上结果并非如此,看下面通过引用传递对象的列子:

  1. <?php 
  2. $aa = new A; 
  3. $bb = &$aa;  // 引用  
  4. $bb->testA = 2; 
  5. /* 
  6.  * 此时$aa, $bb的关系: 
  7.  * 
  8.  *         +-----------+      +-----------------+ 
  9.  * $bb --> | object id | ---> | object(Class A) | 
  10.  *         +-----------+      +-----------------+ 
  11.  *              ^                   
  12.  *              | 
  13.  * $aa ---------+  
  14.  * 
  15.  * 
  16.  */ 
  17. $cc = new B; 
  18. $aa = $cc
  19. $aa->testB = "Changed Class B"
  20. /* 
  21.  * 此时$aa, $bb, $cc的关系: 
  22.  * 
  23.  *         +-----------+      +-----------------+ 
  24.  *         | object id | ---> | object(Class A) | 
  25.  *         +-----------+      +-----------------+ 
  26.  *               
  27.  * $bb ---->-----+       
  28.  *               | 
  29.  * $aa ---->-----+ 
  30.  *               |   
  31.  *               v    
  32.  *         +------------+       
  33.  *         | object id2 | --------------+  
  34.  *         +------------+               | 
  35.  *                                      v 
  36.  *         +------------+      +-----------------+ 
  37.  * $cc --> | object id2 | ---> | object(Class B) | 
  38.  *         +------------+      +-----------------+ 
  39.  */ 
  40. echo "object aa: "; var_dump($aa); //["testB"]=>string(15) "Changed Class B" 
  41. echo "object bb: "; var_dump($bb); //["testB"]=>string(15) "Changed Class B" 
  42. echo "object cc: "; var_dump($cc); //["testB"]=>string(15) "Changed Class B" 
  43. ?> 

此时$aa,$bb,$cc三者内容完全一样,所以可以看出对象并不是按照引用传递,要尽快走出这个误区.

生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生